You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

simple.go 2.2 kB

7 months ago
7 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. package metacache
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. type SimpleMetaCacheConfig[K comparable, V any] struct {
  7. Getter Getter[K, V]
  8. Expire time.Duration
  9. }
  10. type Getter[K comparable, V any] func(keys []K) ([]V, []bool)
  11. type SimpleMetaCache[K comparable, V any] struct {
  12. lock sync.RWMutex
  13. cache map[K]*CacheEntry[K, V]
  14. cfg SimpleMetaCacheConfig[K, V]
  15. }
  16. func NewSimpleMetaCache[K comparable, V any](cfg SimpleMetaCacheConfig[K, V]) *SimpleMetaCache[K, V] {
  17. return &SimpleMetaCache[K, V]{
  18. cache: make(map[K]*CacheEntry[K, V]),
  19. cfg: cfg,
  20. }
  21. }
  22. func (mc *SimpleMetaCache[K, V]) Get(key K) (V, bool) {
  23. var ret V
  24. var ok bool
  25. for i := 0; i < 2; i++ {
  26. mc.lock.RLock()
  27. entry, o := mc.cache[key]
  28. if o {
  29. ret = entry.Data
  30. ok = true
  31. }
  32. mc.lock.RUnlock()
  33. if o {
  34. break
  35. }
  36. mc.load([]K{key})
  37. }
  38. return ret, ok
  39. }
  40. func (mc *SimpleMetaCache[K, V]) GetMany(keys []K) ([]V, []bool) {
  41. result := make([]V, len(keys))
  42. oks := make([]bool, len(keys))
  43. for i := 0; i < 2; i++ {
  44. allGet := true
  45. mc.lock.RLock()
  46. for i, key := range keys {
  47. entry, ok := mc.cache[key]
  48. if ok {
  49. result[i] = entry.Data
  50. oks[i] = true
  51. } else {
  52. allGet = false
  53. }
  54. }
  55. mc.lock.RUnlock()
  56. if allGet {
  57. break
  58. }
  59. mc.load(keys)
  60. }
  61. return result, oks
  62. }
  63. func (mc *SimpleMetaCache[K, V]) load(keys []K) {
  64. vs, getOks := mc.cfg.Getter(keys)
  65. mc.lock.Lock()
  66. defer mc.lock.Unlock()
  67. for i, key := range keys {
  68. if !getOks[i] {
  69. continue
  70. }
  71. _, ok := mc.cache[key]
  72. // 缓存中已有key则认为缓存中是最新的,不再更新
  73. if ok {
  74. continue
  75. }
  76. entry := &CacheEntry[K, V]{
  77. Key: key,
  78. Data: vs[i],
  79. UpdateTime: time.Now(),
  80. }
  81. mc.cache[key] = entry
  82. }
  83. }
  84. func (mc *SimpleMetaCache[K, V]) ClearOutdated() {
  85. mc.lock.Lock()
  86. defer mc.lock.Unlock()
  87. for key, entry := range mc.cache {
  88. dt := time.Since(entry.UpdateTime)
  89. if dt > mc.cfg.Expire || dt < 0 {
  90. delete(mc.cache, key)
  91. }
  92. }
  93. }
  94. func (mc *SimpleMetaCache[K, V]) Drop(keys []K) {
  95. mc.lock.Lock()
  96. defer mc.lock.Unlock()
  97. for _, key := range keys {
  98. delete(mc.cache, key)
  99. }
  100. }
  101. type CacheEntry[K comparable, V any] struct {
  102. Key K
  103. Data V
  104. UpdateTime time.Time
  105. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。