expire.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package cache
  2. import (
  3. "context"
  4. "sync"
  5. "time"
  6. )
  7. type Expire struct {
  8. // The duration while an item is cached.
  9. ItemTTL time.Duration
  10. once sync.Once
  11. mutex sync.RWMutex
  12. size int
  13. items map[string]*memItem
  14. queue []*memItem
  15. }
  16. func (c *Expire) Get(ctx context.Context, key string) (Item, bool) {
  17. c.once.Do(c.init)
  18. c.mutex.RLock()
  19. defer c.mutex.RUnlock()
  20. i, isCached := c.items[key]
  21. if !isCached || i.expiresAt.Before(time.Now()) {
  22. return nil, false
  23. }
  24. return i.value, true
  25. }
  26. func (c *Expire) Set(ctx context.Context, key string, i Item) {
  27. c.once.Do(c.init)
  28. c.mutex.Lock()
  29. defer c.mutex.Unlock()
  30. if i, isCached := c.items[key]; isCached {
  31. c.del(i)
  32. }
  33. c.expire()
  34. c.add(&memItem{
  35. key: key,
  36. expiresAt: time.Now().Add(c.ItemTTL),
  37. value: i,
  38. })
  39. }
  40. func (c *Expire) Del(ctx context.Context, key string) {
  41. c.once.Do(c.init)
  42. c.mutex.Lock()
  43. defer c.mutex.Unlock()
  44. if i, isCached := c.items[key]; isCached {
  45. c.del(i)
  46. c.expire()
  47. }
  48. }
  49. func (c *Expire) Len() int {
  50. c.mutex.RLock()
  51. defer c.mutex.RUnlock()
  52. return len(c.items)
  53. }
  54. func (c *Expire) Size() int {
  55. c.mutex.RLock()
  56. defer c.mutex.RUnlock()
  57. return c.size
  58. }
  59. func (c *Expire) init() {
  60. c.items = make(map[string]*memItem)
  61. }
  62. func (c *Expire) add(i *memItem) {
  63. c.items[i.key] = i
  64. c.queue = append(c.queue, i)
  65. c.size += i.value.Size()
  66. }
  67. func (c *Expire) del(i *memItem) {
  68. if i.value != nil {
  69. delete(c.items, i.key)
  70. c.size -= i.value.Size()
  71. i.value = nil
  72. }
  73. }
  74. func (c *Expire) expire() {
  75. now := time.Now()
  76. i := 0
  77. for i < len(c.queue) && c.queue[i].isExpired(now) {
  78. c.del(c.queue[i])
  79. i++
  80. }
  81. copy(c.queue, c.queue[i:])
  82. c.queue = c.queue[:len(c.queue)-i]
  83. }
  84. type memItem struct {
  85. key string
  86. expiresAt time.Time
  87. value Item
  88. }
  89. func (i *memItem) isExpired(now time.Time) bool {
  90. return i.value == nil || i.expiresAt.Before(now)
  91. }