aboutsummaryrefslogtreecommitdiff
path: root/internal/caching/impl_inmemorylru.go
blob: e99c18d7476bc080beb7f4bd4fe9f57b853c1dcb (plain)
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
package caching

import (
	"fmt"

	lru "github.com/hashicorp/golang-lru"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
)

func NewInMemoryLRUCache(enablePrometheus bool) (*Caches, error) {
	roomVersions, err := NewInMemoryLRUCachePartition(
		RoomVersionCacheName,
		RoomVersionCacheMutable,
		RoomVersionCacheMaxEntries,
		enablePrometheus,
	)
	if err != nil {
		return nil, err
	}
	serverKeys, err := NewInMemoryLRUCachePartition(
		ServerKeyCacheName,
		ServerKeyCacheMutable,
		ServerKeyCacheMaxEntries,
		enablePrometheus,
	)
	if err != nil {
		return nil, err
	}
	roomServerStateKeyNIDs, err := NewInMemoryLRUCachePartition(
		RoomServerStateKeyNIDsCacheName,
		RoomServerStateKeyNIDsCacheMutable,
		RoomServerStateKeyNIDsCacheMaxEntries,
		enablePrometheus,
	)
	if err != nil {
		return nil, err
	}
	roomServerEventTypeNIDs, err := NewInMemoryLRUCachePartition(
		RoomServerEventTypeNIDsCacheName,
		RoomServerEventTypeNIDsCacheMutable,
		RoomServerEventTypeNIDsCacheMaxEntries,
		enablePrometheus,
	)
	if err != nil {
		return nil, err
	}
	roomServerRoomNIDs, err := NewInMemoryLRUCachePartition(
		RoomServerRoomNIDsCacheName,
		RoomServerRoomNIDsCacheMutable,
		RoomServerRoomNIDsCacheMaxEntries,
		enablePrometheus,
	)
	if err != nil {
		return nil, err
	}
	roomServerRoomIDs, err := NewInMemoryLRUCachePartition(
		RoomServerRoomIDsCacheName,
		RoomServerRoomIDsCacheMutable,
		RoomServerRoomIDsCacheMaxEntries,
		enablePrometheus,
	)
	if err != nil {
		return nil, err
	}
	return &Caches{
		RoomVersions:            roomVersions,
		ServerKeys:              serverKeys,
		RoomServerStateKeyNIDs:  roomServerStateKeyNIDs,
		RoomServerEventTypeNIDs: roomServerEventTypeNIDs,
		RoomServerRoomNIDs:      roomServerRoomNIDs,
		RoomServerRoomIDs:       roomServerRoomIDs,
	}, nil
}

type InMemoryLRUCachePartition struct {
	name       string
	mutable    bool
	maxEntries int
	lru        *lru.Cache
}

func NewInMemoryLRUCachePartition(name string, mutable bool, maxEntries int, enablePrometheus bool) (*InMemoryLRUCachePartition, error) {
	var err error
	cache := InMemoryLRUCachePartition{
		name:       name,
		mutable:    mutable,
		maxEntries: maxEntries,
	}
	cache.lru, err = lru.New(maxEntries)
	if err != nil {
		return nil, err
	}
	if enablePrometheus {
		promauto.NewGaugeFunc(prometheus.GaugeOpts{
			Namespace: "dendrite",
			Subsystem: "caching_in_memory_lru",
			Name:      name,
		}, func() float64 {
			return float64(cache.lru.Len())
		})
	}
	return &cache, nil
}

func (c *InMemoryLRUCachePartition) Set(key string, value interface{}) {
	if !c.mutable {
		if peek, ok := c.lru.Peek(key); ok && peek != value {
			panic(fmt.Sprintf("invalid use of immutable cache tries to mutate existing value of %q", key))
		}
	}
	c.lru.Add(key, value)
}

func (c *InMemoryLRUCachePartition) Unset(key string) {
	if !c.mutable {
		panic(fmt.Sprintf("invalid use of immutable cache tries to unset value of %q", key))
	}
	c.lru.Remove(key)
}

func (c *InMemoryLRUCachePartition) Get(key string) (value interface{}, ok bool) {
	return c.lru.Get(key)
}