cache.go 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package ttl_memory_cache
  2. import (
  3. "sync"
  4. "time"
  5. )
  6. type Cache struct {
  7. expiration *time.Duration
  8. cleanupInterval *time.Duration
  9. mu sync.RWMutex
  10. items map[string]Item
  11. }
  12. type Item struct {
  13. Value interface{}
  14. ExpiredAt *time.Time
  15. }
  16. func NewCache(c Config) *Cache {
  17. cache := Cache{
  18. items: make(map[string]Item),
  19. expiration: c.expiration,
  20. cleanupInterval: c.cleanupInterval,
  21. }
  22. if c.cleanupInterval != nil {
  23. go cache.cleanupWorker()
  24. }
  25. return &cache
  26. }
  27. func (c *Cache) Set(key string, value interface{}, expiration *time.Duration) {
  28. item := Item{
  29. Value: value,
  30. }
  31. if expiration != nil {
  32. expiredAt := time.Now().Add(*expiration)
  33. item.ExpiredAt = &expiredAt
  34. } else if c.expiration != nil {
  35. expiredAt := time.Now().Add(*c.expiration)
  36. item.ExpiredAt = &expiredAt
  37. }
  38. c.mu.Lock()
  39. defer c.mu.Unlock()
  40. c.items[key] = item
  41. }
  42. func (c *Cache) Get(key string) (interface{}, bool) {
  43. c.mu.RLock()
  44. defer c.mu.RUnlock()
  45. item, found := c.items[key]
  46. if !found {
  47. return nil, false
  48. }
  49. if item.ExpiredAt != nil && time.Now().After(*item.ExpiredAt) {
  50. c.Delete(key)
  51. return nil, false
  52. }
  53. return item.Value, true
  54. }
  55. func (c *Cache) Delete(key string) {
  56. c.mu.Lock()
  57. defer c.mu.Unlock()
  58. if _, found := c.items[key]; found {
  59. delete(c.items, key)
  60. }
  61. }
  62. func (c *Cache) Clear() {
  63. c.mu.Lock()
  64. defer c.mu.Unlock()
  65. c.items = make(map[string]Item)
  66. }
  67. func (c *Cache) cleanupWorker() {
  68. for {
  69. <-time.After(*c.cleanupInterval)
  70. if len(c.items) == 0 {
  71. return
  72. }
  73. now := time.Now()
  74. for key, item := range c.items {
  75. if item.ExpiredAt != nil && now.After(*item.ExpiredAt) {
  76. c.Delete(key)
  77. }
  78. }
  79. }
  80. }