1
0
mirror of https://github.com/Mrs4s/MiraiGo.git synced 2025-05-04 11:07:40 +08:00
This commit is contained in:
Mrs4s 2020-08-04 14:40:12 +08:00
parent bf8fa81a5d
commit e1e00ed068
3 changed files with 84 additions and 40 deletions

View File

@ -15,6 +15,7 @@ import (
"github.com/Mrs4s/MiraiGo/client/pb/structmsg" "github.com/Mrs4s/MiraiGo/client/pb/structmsg"
"github.com/Mrs4s/MiraiGo/utils" "github.com/Mrs4s/MiraiGo/utils"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"strconv"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -235,12 +236,13 @@ func decodeMessageSvcPacket(c *QQClient, _ uint16, payload []byte) (interface{},
return nil, nil return nil, nil
} }
if friend.msgSeqList == nil { if friend.msgSeqList == nil {
friend.msgSeqList = utils.NewTTList(60) friend.msgSeqList = utils.NewCache(time.Second * 5)
} }
if friend.msgSeqList.Any(func(i interface{}) bool { return i.(int32) == message.Head.MsgSeq }) { strSeq := strconv.FormatInt(int64(message.Head.MsgSeq), 10)
if _, ok := friend.msgSeqList.Get(strSeq); ok {
continue continue
} }
friend.msgSeqList.Add(message.Head.MsgSeq) friend.msgSeqList.Add(strSeq, 0, time.Second*15)
c.dispatchFriendMessage(c.parsePrivateMessage(message)) c.dispatchFriendMessage(c.parsePrivateMessage(message))
case 187: case 187:
_, pkt := c.buildSystemMsgNewFriendPacket() _, pkt := c.buildSystemMsgNewFriendPacket()

View File

@ -37,7 +37,7 @@ type (
Remark string Remark string
FaceId int16 FaceId int16
msgSeqList *utils.TTList msgSeqList *utils.Cache
} }
FriendListResponse struct { FriendListResponse struct {

View File

@ -5,54 +5,96 @@ import (
"time" "time"
) )
type TTList struct { // https://github.com/Konstantin8105/SimpleTTL
list []*item // entry - typical element of cache
lock sync.Mutex type entry struct {
value interface{}
expiry *time.Time
} }
type item struct { // Cache - simple implementation of cache
i interface{} // More information: https://en.wikipedia.org/wiki/Time_to_live
lastAccess int64 type Cache struct {
timeTTL time.Duration
cache map[string]*entry
lock *sync.RWMutex
} }
func NewTTList(ttl int64) *TTList { // NewCache - initialization of new cache.
l := &TTList{} // For avoid mistake - minimal time to live is 1 minute.
// For simplification, - key is string and cache haven`t stop method
func NewCache(interval time.Duration) *Cache {
if interval < time.Second {
interval = time.Second
}
cache := &Cache{
timeTTL: interval,
cache: make(map[string]*entry),
lock: &sync.RWMutex{},
}
go func() { go func() {
for now := range time.Tick(time.Second * 5) { ticker := time.NewTicker(cache.timeTTL)
l.lock.Lock() for {
pos := 0 // wait of ticker
for _, i := range l.list { now := <-ticker.C
if now.Unix()-i.lastAccess > ttl {
l.list = append(l.list[:pos], l.list[pos+1:]...) // remove entry outside TTL
if pos > 0 { cache.lock.Lock()
pos++ for id, entry := range cache.cache {
} if entry.expiry != nil && entry.expiry.Before(now) {
delete(cache.cache, id)
} }
pos++
} }
l.lock.Unlock() cache.lock.Unlock()
} }
}() }()
return l return cache
} }
func (l *TTList) Add(i interface{}) { // Count - return amount element of TTL map.
l.lock.Lock() func (cache *Cache) Count() int {
defer l.lock.Unlock() cache.lock.RLock()
l.list = append(l.list, &item{ defer cache.lock.RUnlock()
i: i,
lastAccess: time.Now().Unix(), return len(cache.cache)
})
} }
func (l *TTList) Any(filter func(i interface{}) bool) bool { // Get - return value from cache
l.lock.Lock() func (cache *Cache) Get(key string) (interface{}, bool) {
defer l.lock.Unlock() cache.lock.RLock()
for _, it := range l.list { defer cache.lock.RUnlock()
if filter(it.i) {
it.lastAccess = time.Now().Unix() e, ok := cache.cache[key]
return true
} if ok && e.expiry != nil && e.expiry.After(time.Now()) {
return e.value, true
} }
return false return nil, false
}
// Add - add key/value in cache
func (cache *Cache) Add(key string, value interface{}, ttl time.Duration) {
cache.lock.Lock()
defer cache.lock.Unlock()
expiry := time.Now().Add(ttl)
cache.cache[key] = &entry{
value: value,
expiry: &expiry,
}
}
// GetKeys - return all keys of cache map
func (cache *Cache) GetKeys() []interface{} {
cache.lock.RLock()
defer cache.lock.RUnlock()
keys := make([]interface{}, len(cache.cache))
var i int
for k := range cache.cache {
keys[i] = k
i++
}
return keys
} }