-
-
Notifications
You must be signed in to change notification settings - Fork 341
Expand file tree
/
Copy pathtopicselectorcache.go
More file actions
54 lines (42 loc) · 1.42 KB
/
topicselectorcache.go
File metadata and controls
54 lines (42 loc) · 1.42 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
package mercure
import (
"github.com/cespare/xxhash/v2"
"github.com/maypok86/otter/v2"
)
// Let's say that a topic selector is 100 bytes on average, a cache with
// 10,000 entries per shard and 256 shards will use about 256 * 10,000 * 100 = 256MB of RAM.
//
// nolint:godox
// TODO: gather stats to find the best default values.
const (
DefaultTopicSelectorStoreCacheMaxEntriesPerShard = 10_000
DefaultTopicSelectorStoreCacheShardCount = uint64(256)
)
// NewTopicSelectorStoreCache creates a TopicSelectorStore with a cache.
func NewTopicSelectorStoreCache(maxEntriesPerShard int, shardCount uint64) (*TopicSelectorStore, error) {
if maxEntriesPerShard == 0 {
return &TopicSelectorStore{}, nil
}
if shardCount == 0 {
shardCount = DefaultTopicSelectorStoreCacheShardCount
}
cacheMap := make(shardedCache, shardCount)
for i := range shardCount {
cacheMap[i] = otter.Must(&otter.Options[string, any]{MaximumSize: maxEntriesPerShard})
}
return &TopicSelectorStore{cache: &cacheMap, skipSelect: true}, nil
}
type shardedCache map[uint64]*otter.Cache[string, any]
func (c *shardedCache) Get(k string) (any, bool) {
return c.getShard(k).GetIfPresent(k)
}
func (c *shardedCache) Set(k string, v any, _ int64) bool {
c.getShard(k).Set(k, v)
return true
}
func (c *shardedCache) getShard(k string) *otter.Cache[string, any] {
h := xxhash.New()
_, _ = h.Write([]byte(k))
s := h.Sum64()
return (*c)[s%uint64(len(*c))]
}