mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-04-03 06:52:13 +08:00
70 lines
1.9 KiB
Go
70 lines
1.9 KiB
Go
|
|
package service
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"strconv"
|
|||
|
|
"strings"
|
|||
|
|
"time"
|
|||
|
|
|
|||
|
|
gocache "github.com/patrickmn/go-cache"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// digestSessionTTL 摘要会话默认 TTL
|
|||
|
|
const digestSessionTTL = 5 * time.Minute
|
|||
|
|
|
|||
|
|
// sessionEntry flat cache 条目
|
|||
|
|
type sessionEntry struct {
|
|||
|
|
uuid string
|
|||
|
|
accountID int64
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// DigestSessionStore 内存摘要会话存储(flat cache 实现)
|
|||
|
|
// key: "{groupID}:{prefixHash}|{digestChain}" → *sessionEntry
|
|||
|
|
type DigestSessionStore struct {
|
|||
|
|
cache *gocache.Cache
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// NewDigestSessionStore 创建内存摘要会话存储
|
|||
|
|
func NewDigestSessionStore() *DigestSessionStore {
|
|||
|
|
return &DigestSessionStore{
|
|||
|
|
cache: gocache.New(digestSessionTTL, time.Minute),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Save 保存摘要会话。oldDigestChain 为 Find 返回的 matchedChain,用于删旧 key。
|
|||
|
|
func (s *DigestSessionStore) Save(groupID int64, prefixHash, digestChain, uuid string, accountID int64, oldDigestChain string) {
|
|||
|
|
if digestChain == "" {
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
ns := buildNS(groupID, prefixHash)
|
|||
|
|
s.cache.Set(ns+digestChain, &sessionEntry{uuid: uuid, accountID: accountID}, gocache.DefaultExpiration)
|
|||
|
|
if oldDigestChain != "" && oldDigestChain != digestChain {
|
|||
|
|
s.cache.Delete(ns + oldDigestChain)
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Find 查找摘要会话,从完整 chain 逐段截断,返回最长匹配及对应 matchedChain。
|
|||
|
|
func (s *DigestSessionStore) Find(groupID int64, prefixHash, digestChain string) (uuid string, accountID int64, matchedChain string, found bool) {
|
|||
|
|
if digestChain == "" {
|
|||
|
|
return "", 0, "", false
|
|||
|
|
}
|
|||
|
|
ns := buildNS(groupID, prefixHash)
|
|||
|
|
chain := digestChain
|
|||
|
|
for {
|
|||
|
|
if val, ok := s.cache.Get(ns + chain); ok {
|
|||
|
|
if e, ok := val.(*sessionEntry); ok {
|
|||
|
|
return e.uuid, e.accountID, chain, true
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
i := strings.LastIndex(chain, "-")
|
|||
|
|
if i < 0 {
|
|||
|
|
return "", 0, "", false
|
|||
|
|
}
|
|||
|
|
chain = chain[:i]
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// buildNS 构建 namespace 前缀
|
|||
|
|
func buildNS(groupID int64, prefixHash string) string {
|
|||
|
|
return strconv.FormatInt(groupID, 10) + ":" + prefixHash + "|"
|
|||
|
|
}
|