From 771892277e76a89f5dd7bd6623f79578497b4ddd Mon Sep 17 00:00:00 2001 From: arsam Date: Fri, 18 Sep 2026 23:06:29 +0330 Subject: [PATCH] Import source: axon/services/cache Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality. --- axon/services/cache.py | 75 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 axon/services/cache.py diff --git a/axon/services/cache.py b/axon/services/cache.py new file mode 100644 index 0000000..8eb2032 --- /dev/null +++ b/axon/services/cache.py @@ -0,0 +1,75 @@ +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}"