-
Notifications
You must be signed in to change notification settings - Fork 687
/
generic_cache.go
113 lines (98 loc) · 2.79 KB
/
generic_cache.go
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
package common
import (
"time"
)
type cacheItem[T any] struct {
value T
validTime time.Time
}
// Cache is a generic cache implementation with TOL (time of live) for each item
type Cache[K comparable, T any] struct {
data map[K]cacheItem[T] // map[K]T is a map with key type K and value type T
timeOfLiveItems time.Duration
timerProvider TimeProvider
}
// NewCache creates a new cache
func NewCache[K comparable, T any](timerProvider TimeProvider, timeOfLiveItems time.Duration) *Cache[K, T] {
return &Cache[K, T]{
data: make(map[K]cacheItem[T]),
timeOfLiveItems: timeOfLiveItems,
timerProvider: timerProvider}
}
// Get returns the value of the key and true if the key exists and is not outdated
func (c *Cache[K, T]) Get(key K) (T, bool) {
item, ok := c.data[key]
if !ok {
var zeroValue T
return zeroValue, false
}
// If the item is outdated, return zero value and remove from cache
if item.validTime.Before(c.timerProvider.Now()) {
delete(c.data, key)
var zeroValue T
return zeroValue, false
}
// We extend the life of the item if it is used
item.validTime = c.timerProvider.Now().Add(c.timeOfLiveItems)
c.data[key] = item
return item.value, true
}
// GetOrDefault returns the value of the key and defaultValue if the key does not exist or is outdated
func (c *Cache[K, T]) GetOrDefault(key K, defaultValue T) T {
item, ok := c.Get(key)
if !ok {
return defaultValue
}
return item
}
// Set sets the value of the key
func (c *Cache[K, T]) Set(key K, value T) {
c.data[key] = cacheItem[T]{value: value, validTime: c.timerProvider.Now().Add(c.timeOfLiveItems)}
}
// Delete deletes the key from the cache
func (c *Cache[K, T]) Delete(key K) {
delete(c.data, key)
}
// Len returns the number of items in the cache
func (c *Cache[K, T]) Len() int {
return len(c.data)
}
// Keys returns the keys of the cache
func (c *Cache[K, T]) Keys() []K {
keys := make([]K, 0, len(c.data))
for k := range c.data {
keys = append(keys, k)
}
return keys
}
// Values returns the values of the cache
func (c *Cache[K, T]) Values() []T {
values := make([]T, 0, len(c.data))
for _, v := range c.data {
values = append(values, v.value)
}
return values
}
// Clear clears the cache
func (c *Cache[K, T]) Clear() {
c.data = make(map[K]cacheItem[T])
}
// DeleteOutdated deletes the outdated items from the cache
func (c *Cache[K, T]) DeleteOutdated() {
for k, v := range c.data {
if isOutdated(v.validTime, c.timerProvider.Now()) {
delete(c.data, k)
}
}
}
func isOutdated(validTime time.Time, now time.Time) bool {
return validTime.Before(now)
}
// RenewEntry renews the entry of the key
func (c *Cache[K, T]) RenewEntry(key K, validTime time.Time) {
item, ok := c.data[key]
if ok {
item.validTime = c.timerProvider.Now().Add(c.timeOfLiveItems)
c.data[key] = item
}
}