-
Notifications
You must be signed in to change notification settings - Fork 0
/
faststructcache.go
88 lines (76 loc) · 2.21 KB
/
faststructcache.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
package faststructcache
import (
"github.com/VictoriaMetrics/fastcache"
"github.com/kelindar/binary"
"github.com/klauspost/compress/s2"
)
type (
// FastStructCache is an in-memory key-value store intended to be able to store larger
// structs (although any data type should work).
// It wraps fastcache from VictoriaMetrics with the binary codec from kelindar,
// and optional snappy-like compression (S2 from klauspost).
FastStructCache[KT, VT any] struct {
Cache *fastcache.Cache
compress bool
}
)
// New returns new cache with the given maxBytes capacity in bytes (min 32MB), with optional light compression.
func New[KT, VT any](mb int, compress bool) FastStructCache[KT, VT] {
return FastStructCache[KT, VT]{Cache: fastcache.New(mb * 1024 * 1024), compress: compress}
}
// Set stores (k, v) in the cache.
func (c FastStructCache[KT, VT]) Set(k KT, v VT) {
c.Cache.Set(c.encode(k, v))
}
// Get returns pointer to a value stored for given key k, or nil if it didn't exist in the cache
func (c FastStructCache[KT, VT]) Get(k KT) *VT {
encodedVal, exists := c.Cache.HasGet(nil, c.encodeKey(k))
if !exists {
return nil
}
return c.decodeVal(encodedVal)
}
// Has returns true if entry for the given key k exists in the cache.
func (c FastStructCache[KT, VT]) Has(k KT) bool {
return c.Cache.Has(c.encodeKey(k))
}
// Del deletes value for the given k from the cache.
func (c FastStructCache[KT, VT]) Del(k KT) {
c.Cache.Del(c.encodeKey(k))
}
// Reset removes all the items from the cache.
func (c FastStructCache[KT, VT]) Reset() {
c.Cache.Reset()
}
func (c FastStructCache[KT, VT]) encode(k KT, v VT) ([]byte, []byte) {
encodedVal, err := binary.Marshal(v)
if c.compress {
encodedVal = s2.Encode(nil, encodedVal)
}
if err != nil {
panic(err)
}
return c.encodeKey(k), encodedVal
}
func (c FastStructCache[KT, VT]) encodeKey(k KT) []byte {
encodedKey, err := binary.Marshal(k)
if err != nil {
panic(err)
}
return encodedKey
}
func (c FastStructCache[KT, VT]) decodeVal(encodedVal []byte) *VT {
if c.compress {
var err error
encodedVal, err = s2.Decode(nil, encodedVal)
if err != nil {
panic(err)
}
}
var v VT
err := binary.Unmarshal(encodedVal, &v)
if err != nil {
panic(err)
}
return &v
}