mirror of
https://github.com/hoernschen/dendrite.git
synced 2025-07-29 12:42:46 +00:00
More flexible caching (#1101)
This commit is contained in:
parent
76ff47c052
commit
e7b19d2c70
16 changed files with 189 additions and 142 deletions
|
@ -66,7 +66,7 @@ type BaseDendrite struct {
|
|||
UseHTTPAPIs bool
|
||||
httpClient *http.Client
|
||||
Cfg *config.Dendrite
|
||||
ImmutableCache caching.ImmutableCache
|
||||
Caches *caching.Caches
|
||||
KafkaConsumer sarama.Consumer
|
||||
KafkaProducer sarama.SyncProducer
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ func NewBaseDendrite(cfg *config.Dendrite, componentName string, useHTTPAPIs boo
|
|||
kafkaConsumer, kafkaProducer = setupKafka(cfg)
|
||||
}
|
||||
|
||||
cache, err := caching.NewImmutableInMemoryLRUCache()
|
||||
cache, err := caching.NewInMemoryLRUCache()
|
||||
if err != nil {
|
||||
logrus.WithError(err).Warnf("Failed to create cache")
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func NewBaseDendrite(cfg *config.Dendrite, componentName string, useHTTPAPIs boo
|
|||
UseHTTPAPIs: useHTTPAPIs,
|
||||
tracerCloser: closer,
|
||||
Cfg: cfg,
|
||||
ImmutableCache: cache,
|
||||
Caches: cache,
|
||||
PublicAPIMux: httpmux.PathPrefix(httpapis.PublicPathPrefix).Subrouter().UseEncodedPath(),
|
||||
InternalAPIMux: httpmux.PathPrefix(httpapis.InternalPathPrefix).Subrouter().UseEncodedPath(),
|
||||
httpClient: &client,
|
||||
|
@ -151,7 +151,7 @@ func (b *BaseDendrite) AppserviceHTTPClient() appserviceAPI.AppServiceQueryAPI {
|
|||
|
||||
// RoomserverHTTPClient returns RoomserverInternalAPI for hitting the roomserver over HTTP.
|
||||
func (b *BaseDendrite) RoomserverHTTPClient() roomserverAPI.RoomserverInternalAPI {
|
||||
rsAPI, err := rsinthttp.NewRoomserverClient(b.Cfg.RoomServerURL(), b.httpClient, b.ImmutableCache)
|
||||
rsAPI, err := rsinthttp.NewRoomserverClient(b.Cfg.RoomServerURL(), b.httpClient, b.Caches)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Panic("RoomserverHTTPClient failed", b.httpClient)
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ func (b *BaseDendrite) ServerKeyAPIClient() serverKeyAPI.ServerKeyInternalAPI {
|
|||
f, err := skinthttp.NewServerKeyClient(
|
||||
b.Cfg.ServerKeyAPIURL(),
|
||||
b.httpClient,
|
||||
b.ImmutableCache,
|
||||
b.Caches,
|
||||
)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Panic("NewServerKeyInternalAPIHTTP failed", b.httpClient)
|
||||
|
|
30
internal/caching/cache_roomversions.go
Normal file
30
internal/caching/cache_roomversions.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package caching
|
||||
|
||||
import "github.com/matrix-org/gomatrixserverlib"
|
||||
|
||||
const (
|
||||
RoomVersionCacheName = "room_versions"
|
||||
RoomVersionCacheMaxEntries = 1024
|
||||
RoomVersionCacheMutable = false
|
||||
)
|
||||
|
||||
// RoomVersionsCache contains the subset of functions needed for
|
||||
// a room version cache.
|
||||
type RoomVersionCache interface {
|
||||
GetRoomVersion(roomID string) (roomVersion gomatrixserverlib.RoomVersion, ok bool)
|
||||
StoreRoomVersion(roomID string, roomVersion gomatrixserverlib.RoomVersion)
|
||||
}
|
||||
|
||||
func (c Caches) GetRoomVersion(roomID string) (gomatrixserverlib.RoomVersion, bool) {
|
||||
val, found := c.RoomVersions.Get(roomID)
|
||||
if found && val != nil {
|
||||
if roomVersion, ok := val.(gomatrixserverlib.RoomVersion); ok {
|
||||
return roomVersion, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (c Caches) StoreRoomVersion(roomID string, roomVersion gomatrixserverlib.RoomVersion) {
|
||||
c.RoomVersions.Set(roomID, roomVersion)
|
||||
}
|
41
internal/caching/cache_serverkeys.go
Normal file
41
internal/caching/cache_serverkeys.go
Normal file
|
@ -0,0 +1,41 @@
|
|||
package caching
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
const (
|
||||
ServerKeyCacheName = "server_key"
|
||||
ServerKeyCacheMaxEntries = 4096
|
||||
ServerKeyCacheMutable = true
|
||||
)
|
||||
|
||||
// ServerKeyCache contains the subset of functions needed for
|
||||
// a server key cache.
|
||||
type ServerKeyCache interface {
|
||||
GetServerKey(request gomatrixserverlib.PublicKeyLookupRequest) (response gomatrixserverlib.PublicKeyLookupResult, ok bool)
|
||||
StoreServerKey(request gomatrixserverlib.PublicKeyLookupRequest, response gomatrixserverlib.PublicKeyLookupResult)
|
||||
}
|
||||
|
||||
func (c Caches) GetServerKey(
|
||||
request gomatrixserverlib.PublicKeyLookupRequest,
|
||||
) (gomatrixserverlib.PublicKeyLookupResult, bool) {
|
||||
key := fmt.Sprintf("%s/%s", request.ServerName, request.KeyID)
|
||||
val, found := c.ServerKeys.Get(key)
|
||||
if found && val != nil {
|
||||
if keyLookupResult, ok := val.(gomatrixserverlib.PublicKeyLookupResult); ok {
|
||||
return keyLookupResult, true
|
||||
}
|
||||
}
|
||||
return gomatrixserverlib.PublicKeyLookupResult{}, false
|
||||
}
|
||||
|
||||
func (c Caches) StoreServerKey(
|
||||
request gomatrixserverlib.PublicKeyLookupRequest,
|
||||
response gomatrixserverlib.PublicKeyLookupResult,
|
||||
) {
|
||||
key := fmt.Sprintf("%s/%s", request.ServerName, request.KeyID)
|
||||
c.ServerKeys.Set(key, response)
|
||||
}
|
15
internal/caching/caches.go
Normal file
15
internal/caching/caches.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
package caching
|
||||
|
||||
// Caches contains a set of references to caches. They may be
|
||||
// different implementations as long as they satisfy the Cache
|
||||
// interface.
|
||||
type Caches struct {
|
||||
RoomVersions Cache // implements RoomVersionCache
|
||||
ServerKeys Cache // implements ServerKeyCache
|
||||
}
|
||||
|
||||
// Cache is the interface that an implementation must satisfy.
|
||||
type Cache interface {
|
||||
Get(key string) (value interface{}, ok bool)
|
||||
Set(key string, value interface{})
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
package caching
|
||||
|
||||
import (
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
)
|
||||
|
||||
const (
|
||||
RoomVersionMaxCacheEntries = 1024
|
||||
ServerKeysMaxCacheEntries = 1024
|
||||
)
|
||||
|
||||
type ImmutableCache interface {
|
||||
GetRoomVersion(roomId string) (gomatrixserverlib.RoomVersion, bool)
|
||||
StoreRoomVersion(roomId string, roomVersion gomatrixserverlib.RoomVersion)
|
||||
GetServerKey(request gomatrixserverlib.PublicKeyLookupRequest) (gomatrixserverlib.PublicKeyLookupResult, bool)
|
||||
StoreServerKey(request gomatrixserverlib.PublicKeyLookupRequest, response gomatrixserverlib.PublicKeyLookupResult)
|
||||
}
|
|
@ -1,95 +0,0 @@
|
|||
package caching
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
)
|
||||
|
||||
type ImmutableInMemoryLRUCache struct {
|
||||
roomVersions *lru.Cache
|
||||
serverKeys *lru.Cache
|
||||
}
|
||||
|
||||
func NewImmutableInMemoryLRUCache() (*ImmutableInMemoryLRUCache, error) {
|
||||
roomVersionCache, rvErr := lru.New(RoomVersionMaxCacheEntries)
|
||||
if rvErr != nil {
|
||||
return nil, rvErr
|
||||
}
|
||||
serverKeysCache, rvErr := lru.New(ServerKeysMaxCacheEntries)
|
||||
if rvErr != nil {
|
||||
return nil, rvErr
|
||||
}
|
||||
cache := &ImmutableInMemoryLRUCache{
|
||||
roomVersions: roomVersionCache,
|
||||
serverKeys: serverKeysCache,
|
||||
}
|
||||
cache.configureMetrics()
|
||||
return cache, nil
|
||||
}
|
||||
|
||||
func (c *ImmutableInMemoryLRUCache) configureMetrics() {
|
||||
promauto.NewGaugeFunc(prometheus.GaugeOpts{
|
||||
Namespace: "dendrite",
|
||||
Subsystem: "caching",
|
||||
Name: "number_room_version_entries",
|
||||
Help: "The number of room version entries cached.",
|
||||
}, func() float64 {
|
||||
return float64(c.roomVersions.Len())
|
||||
})
|
||||
|
||||
promauto.NewGaugeFunc(prometheus.GaugeOpts{
|
||||
Namespace: "dendrite",
|
||||
Subsystem: "caching",
|
||||
Name: "number_server_key_entries",
|
||||
Help: "The number of server key entries cached.",
|
||||
}, func() float64 {
|
||||
return float64(c.serverKeys.Len())
|
||||
})
|
||||
}
|
||||
|
||||
func checkForInvalidMutation(cache *lru.Cache, key string, value interface{}) {
|
||||
if peek, ok := cache.Peek(key); ok && peek != value {
|
||||
panic(fmt.Sprintf("invalid use of immutable cache tries to mutate existing value of %q", key))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ImmutableInMemoryLRUCache) GetRoomVersion(roomID string) (gomatrixserverlib.RoomVersion, bool) {
|
||||
val, found := c.roomVersions.Get(roomID)
|
||||
if found && val != nil {
|
||||
if roomVersion, ok := val.(gomatrixserverlib.RoomVersion); ok {
|
||||
return roomVersion, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func (c *ImmutableInMemoryLRUCache) StoreRoomVersion(roomID string, roomVersion gomatrixserverlib.RoomVersion) {
|
||||
checkForInvalidMutation(c.roomVersions, roomID, roomVersion)
|
||||
c.roomVersions.Add(roomID, roomVersion)
|
||||
}
|
||||
|
||||
func (c *ImmutableInMemoryLRUCache) GetServerKey(
|
||||
request gomatrixserverlib.PublicKeyLookupRequest,
|
||||
) (gomatrixserverlib.PublicKeyLookupResult, bool) {
|
||||
key := fmt.Sprintf("%s/%s", request.ServerName, request.KeyID)
|
||||
val, found := c.serverKeys.Get(key)
|
||||
if found && val != nil {
|
||||
if keyLookupResult, ok := val.(gomatrixserverlib.PublicKeyLookupResult); ok {
|
||||
return keyLookupResult, true
|
||||
}
|
||||
}
|
||||
return gomatrixserverlib.PublicKeyLookupResult{}, false
|
||||
}
|
||||
|
||||
func (c *ImmutableInMemoryLRUCache) StoreServerKey(
|
||||
request gomatrixserverlib.PublicKeyLookupRequest,
|
||||
response gomatrixserverlib.PublicKeyLookupResult,
|
||||
) {
|
||||
key := fmt.Sprintf("%s/%s", request.ServerName, request.KeyID)
|
||||
checkForInvalidMutation(c.roomVersions, key, response)
|
||||
c.serverKeys.Add(request, response)
|
||||
}
|
73
internal/caching/impl_inmemorylru.go
Normal file
73
internal/caching/impl_inmemorylru.go
Normal file
|
@ -0,0 +1,73 @@
|
|||
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() (*Caches, error) {
|
||||
roomVersions, err := NewInMemoryLRUCachePartition(
|
||||
RoomVersionCacheName,
|
||||
RoomVersionCacheMutable,
|
||||
RoomVersionCacheMaxEntries,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
serverKeys, err := NewInMemoryLRUCachePartition(
|
||||
ServerKeyCacheName,
|
||||
ServerKeyCacheMutable,
|
||||
ServerKeyCacheMaxEntries,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Caches{
|
||||
RoomVersions: roomVersions,
|
||||
ServerKeys: serverKeys,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type InMemoryLRUCachePartition struct {
|
||||
name string
|
||||
mutable bool
|
||||
maxEntries int
|
||||
lru *lru.Cache
|
||||
}
|
||||
|
||||
func NewInMemoryLRUCachePartition(name string, mutable bool, maxEntries int) (*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
|
||||
}
|
||||
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) Get(key string) (value interface{}, ok bool) {
|
||||
return c.lru.Get(key)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue