Files
Axon/axon/services/cache.py
T
arsam 771892277e Import source: axon/services/cache
Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
2026-09-18 23:06:29 +03:30

76 lines
2.1 KiB
Python

import hashlib
import json
import logging
from datetime import UTC, datetime, timedelta
logger = logging.getLogger(__name__)
class InMemoryCache:
def __init__(self) -> None:
self._store: dict[str, tuple[str, datetime]] = {}
async def get(self, key: str) -> str | None:
if key not in self._store:
return None
value, expires_at = self._store[key]
if datetime.now(UTC) >= expires_at:
del self._store[key]
return None
return value
async def set(self, key: str, value: str, ttl: int = 600) -> None:
self._store[key] = (value, datetime.now(UTC) + timedelta(seconds=ttl))
async def ping(self) -> bool:
return True
class RedisCache:
def __init__(self, client) -> None:
self._client = client
async def get(self, key: str) -> str | None:
return await self._client.get(key)
async def set(self, key: str, value: str, ttl: int = 600) -> None:
await self._client.setex(key, ttl, value)
async def ping(self) -> bool:
try:
await self._client.ping()
return True
except Exception:
return False
_cache: InMemoryCache | RedisCache | None = None
async def get_cache() -> InMemoryCache | RedisCache:
global _cache
if _cache is not None:
return _cache
from axon.config import settings
if settings.redis_url:
try:
import redis.asyncio as aioredis
client = aioredis.from_url(settings.redis_url, decode_responses=True)
await client.ping()
_cache = RedisCache(client)
logger.info("Connected to Redis at %s", settings.redis_url)
return _cache
except Exception as exc:
logger.warning("Redis unavailable (%s), falling back to in-memory cache", exc)
_cache = InMemoryCache()
return _cache
def make_cache_key(prefix: str, **kwargs) -> str:
payload = json.dumps(kwargs, sort_keys=True, default=str)
digest = hashlib.sha256(payload.encode()).hexdigest()
return f"{prefix}:{digest}"