Skip to content
This repository was archived by the owner on Mar 26, 2024. It is now read-only.

Commit b78742d

Browse files
committed
Add redis caches implementation
1 parent 1c291e5 commit b78742d

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
from typing import Any, Generic, Optional, Union, TYPE_CHECKING
2+
from functools import wraps
3+
4+
from synapse.util.caches.lrucache import KT, VT, AsyncLruCache, T
5+
6+
if TYPE_CHECKING:
7+
from synapse.replication.tcp.external_sharded_cache import ExternalShardedCache
8+
9+
10+
def redisCachedList(redis_shard_cache, cache_name, list_name):
11+
def decorator(f):
12+
@wraps(f)
13+
async def _wrapped(**kwargs):
14+
keys = kwargs[list_name]
15+
values = await redis_shard_cache.mget(cache_name, keys)
16+
17+
missing_keys = set(keys) - set(values.keys())
18+
kwargs[list_name] = missing_keys
19+
missing_values = await f(**kwargs)
20+
await redis_shard_cache.mset(cache_name, missing_values)
21+
22+
values.update(missing_values)
23+
return values
24+
return _wrapped
25+
return decorator
26+
27+
28+
def _redis_key(key: KT) -> str:
29+
if isinstance(key, tuple):
30+
return key[0]
31+
return f"{key}"
32+
33+
34+
class RedisLruCache(AsyncLruCache, Generic[KT, VT]):
35+
def __init__(
36+
self,
37+
redis_shard_cache: "ExternalShardedCache",
38+
cache_name: str,
39+
max_size: int,
40+
):
41+
super().__init__(cache_name=cache_name, max_size=max_size)
42+
self.cache_name = cache_name
43+
self.redis_shard_cache = redis_shard_cache
44+
45+
async def get(
46+
self, key: KT, default: Optional[T] = None, update_metrics: bool = True
47+
) -> Union[None, VT, T]:
48+
local_value = await super().get(
49+
key, default=default, update_metrics=update_metrics
50+
)
51+
if local_value is not default:
52+
return local_value
53+
54+
redis_value = await self.redis_shard_cache.get(self.cache_name, _redis_key(key))
55+
if redis_value:
56+
await super().set(key, redis_value)
57+
return redis_value
58+
59+
return default
60+
61+
async def set(self, key: KT, value: Any) -> None:
62+
await self.redis_shard_cache.set(self.cache_name, _redis_key(key), value)
63+
await super().set(key, value)
64+
65+
async def invalidate(self, key: KT) -> None:
66+
await self.redis_shard_cache.delete(self.cache_name, _redis_key(key))
67+
await super().invalidate(key)
68+
69+
async def contains(self, key: KT) -> bool:
70+
if await super().contains(key):
71+
return True
72+
73+
if await self.redis_shard_cache.contains(self.cache_name, _redis_key(key)):
74+
return True
75+
76+
return False

0 commit comments

Comments
 (0)