forked from hhftechnology/traefik-queue-manager
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinternal_cache.go
More file actions
145 lines (124 loc) · 3.16 KB
/
internal_cache.go
File metadata and controls
145 lines (124 loc) · 3.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// internal_cache.go
package traefik_queue_manager
import (
"sync"
"time"
)
// Item represents a cached item with expiration
type CacheItem struct {
Object interface{}
Expiration int64 // Unix nano time when this item expires
}
// SimpleCache provides a thread-safe in-memory key/value store with expiration
type SimpleCache struct {
items map[string]CacheItem
mu sync.RWMutex
defaultExpiration time.Duration
cleanupInterval time.Duration
stopCleanup chan bool
}
// Constants for expiration
const (
NoExpiration time.Duration = -1
DefaultExpiration time.Duration = 0
)
// NewSimpleCache creates a new cache with the provided default expiration duration
// and cleanup interval. If the cleanup interval is <= 0, expired items are not
// automatically deleted from the cache.
func NewSimpleCache(defaultExpiration, cleanupInterval time.Duration) *SimpleCache {
cache := &SimpleCache{
items: make(map[string]CacheItem),
defaultExpiration: defaultExpiration,
cleanupInterval: cleanupInterval,
}
// Start the cleanup goroutine if a cleanup interval is specified
if cleanupInterval > 0 {
cache.stopCleanup = make(chan bool)
go cache.startCleanupTimer()
}
return cache
}
// startCleanupTimer starts a timer that periodically cleans up expired items
func (c *SimpleCache) startCleanupTimer() {
ticker := time.NewTicker(c.cleanupInterval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
c.DeleteExpired()
case <-c.stopCleanup:
return
}
}
}
// Set adds an item to the cache, replacing any existing item with the same key
func (c *SimpleCache) Set(k string, x interface{}, d time.Duration) {
var exp int64
if d == DefaultExpiration {
d = c.defaultExpiration
}
if d > 0 {
exp = time.Now().Add(d).UnixNano()
}
c.mu.Lock()
c.items[k] = CacheItem{
Object: x,
Expiration: exp,
}
c.mu.Unlock()
}
// Get retrieves an item from the cache and returns (item, found)
func (c *SimpleCache) Get(k string) (interface{}, bool) {
c.mu.RLock()
item, found := c.items[k]
if !found {
c.mu.RUnlock()
return nil, false
}
// Check if the item has expired
if item.Expiration > 0 {
if time.Now().UnixNano() > item.Expiration {
c.mu.RUnlock()
return nil, false
}
}
c.mu.RUnlock()
return item.Object, true
}
// Delete removes an item from the cache
func (c *SimpleCache) Delete(k string) {
c.mu.Lock()
delete(c.items, k)
c.mu.Unlock()
}
// DeleteExpired deletes all expired items from the cache
func (c *SimpleCache) DeleteExpired() {
now := time.Now().UnixNano()
c.mu.Lock()
defer c.mu.Unlock()
for k, v := range c.items {
// Delete if the item has expired
if v.Expiration > 0 && now > v.Expiration {
delete(c.items, k)
}
}
}
// Stop ends the cleanup timer if it's running
func (c *SimpleCache) Stop() {
if c.cleanupInterval > 0 {
c.stopCleanup <- true
}
}
// ItemCount returns the number of items in the cache (including expired items)
func (c *SimpleCache) ItemCount() int {
c.mu.RLock()
n := len(c.items)
c.mu.RUnlock()
return n
}
// Flush deletes all items from the cache
func (c *SimpleCache) Flush() {
c.mu.Lock()
c.items = make(map[string]CacheItem)
c.mu.Unlock()
}