digest_session_store.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package service
  2. import (
  3. "strconv"
  4. "strings"
  5. "time"
  6. gocache "github.com/patrickmn/go-cache"
  7. )
  8. // digestSessionTTL 摘要会话默认 TTL
  9. const digestSessionTTL = 5 * time.Minute
  10. // sessionEntry flat cache 条目
  11. type sessionEntry struct {
  12. uuid string
  13. accountID int64
  14. }
  15. // DigestSessionStore 内存摘要会话存储(flat cache 实现)
  16. // key: "{groupID}:{prefixHash}|{digestChain}" → *sessionEntry
  17. type DigestSessionStore struct {
  18. cache *gocache.Cache
  19. }
  20. // NewDigestSessionStore 创建内存摘要会话存储
  21. func NewDigestSessionStore() *DigestSessionStore {
  22. return &DigestSessionStore{
  23. cache: gocache.New(digestSessionTTL, time.Minute),
  24. }
  25. }
  26. // Save 保存摘要会话。oldDigestChain 为 Find 返回的 matchedChain,用于删旧 key。
  27. func (s *DigestSessionStore) Save(groupID int64, prefixHash, digestChain, uuid string, accountID int64, oldDigestChain string) {
  28. if digestChain == "" {
  29. return
  30. }
  31. ns := buildNS(groupID, prefixHash)
  32. s.cache.Set(ns+digestChain, &sessionEntry{uuid: uuid, accountID: accountID}, gocache.DefaultExpiration)
  33. if oldDigestChain != "" && oldDigestChain != digestChain {
  34. s.cache.Delete(ns + oldDigestChain)
  35. }
  36. }
  37. // Find 查找摘要会话,从完整 chain 逐段截断,返回最长匹配及对应 matchedChain。
  38. func (s *DigestSessionStore) Find(groupID int64, prefixHash, digestChain string) (uuid string, accountID int64, matchedChain string, found bool) {
  39. if digestChain == "" {
  40. return "", 0, "", false
  41. }
  42. ns := buildNS(groupID, prefixHash)
  43. chain := digestChain
  44. for {
  45. if val, ok := s.cache.Get(ns + chain); ok {
  46. if e, ok := val.(*sessionEntry); ok {
  47. return e.uuid, e.accountID, chain, true
  48. }
  49. }
  50. i := strings.LastIndex(chain, "-")
  51. if i < 0 {
  52. return "", 0, "", false
  53. }
  54. chain = chain[:i]
  55. }
  56. }
  57. // buildNS 构建 namespace 前缀
  58. func buildNS(groupID int64, prefixHash string) string {
  59. return strconv.FormatInt(groupID, 10) + ":" + prefixHash + "|"
  60. }