import orjson as json from redis.asyncio import ConnectionPool, Redis from typing import Any, Dict, List, Tuple from server.cache.formatters import decode_str from server.cache.key_getters import get_key, get_key_by_template from server.cache.modes import CacheMode, cache_mode _caches: dict async def init_cache(**config) -> Redis: """Init and return cache instance.""" global _caches pool = ConnectionPool(**config, decode_responses=True) redis_client = await Redis(connection_pool=pool) _caches = {"default": RedisCache(redis_client)} return redis_client class RedisCache: """Redis cache.""" def __init__(self, cache_client: Redis, alias="default"): self.alias = alias self.cache_client = cache_client async def get(self, cache_key: str, str_to_date: bool = False) -> Any: """Get data by key (as it is) final version.""" result = None if cache_mode.get() == CacheMode.REGULAR: result = await self.cache_client.get(cache_key) if result: return decode_str(result) if str_to_date else json.loads(result) async def set(self, cache_key: str or None, cache_ttl: int, data: Any, serialize: bool = True): """Put data to redis. Args: cache_key: Key. cache_ttl: TTL. data: Value. serialize: If True, data will be serialized to JSON. """ if cache_ttl <= 0 or cache_mode.get() == CacheMode.IGNORE: return if cache_key: serialized_data = json.dumps(data, default=str) if serialize else data await self.cache_client.set(cache_key, serialized_data, ex=cache_ttl) async def clear(self): return await self.cache_client.flushdb() def get_cache(alias="default") -> RedisCache: """Get cache instance by alias.""" return _caches.get(alias) async def get_value_by_str_key( cache_key: str, cache_client: RedisCache or None = None, hashed=True, str_to_date: bool = False ) -> Any: cache_full_key = get_key(cache_key, hashed=hashed) if not cache_client: cache_client = get_cache() value = await cache_client.get(cache_full_key, str_to_date=str_to_date) return value, cache_full_key async def get_value_by_key_template( cache_key_template: str, defined_args: List[str] or None = None, args: Tuple or None = None, kwargs: Dict or None = None, key_args_indexes: Tuple[int] or None = None, key_args: Tuple[Any] or None = None, key_kwargs: Dict[str, Any] or None = None, cache_client: Redis or None = None, str_to_date: bool = True, ): """Generate key and get data from redis. Args: cache_key_template: Cache key template. kwargs: Func call kwargs. defined_args: Function full args spec. args: Func call args. key_args_indexes: Cache key parts indexes in args or None if use all args. key_args: Additional key args. key_kwargs: Additional key kwargs. cache_client: Redis client. str_to_date: Convert strings to dates. Returns: Redis data and generated key. """ cache_key = get_key_by_template( cache_key_template, defined_args, args, kwargs, key_args_indexes, key_args, key_kwargs ) if not cache_client: cache_client = get_cache() value = await cache_client.get(cache_key, str_to_date=str_to_date) return value, cache_key