from datetime import UTC, datetime import pytest from src.services.operator_summary_cache import ( clear_operator_summary_cache, get_cached_operator_summary_async, get_cached_operator_summary, store_operator_summary_async, store_operator_summary, ) class _FakeRedis: def __init__(self) -> None: self.values: dict[str, str] = {} self.expirations: dict[str, int] = {} async def get(self, key: str) -> str | None: return self.values.get(key) async def set(self, key: str, value: str, ex: int) -> bool: self.values[key] = value self.expirations[key] = ex return True async def delete(self, key: str) -> int: return 1 if self.values.pop(key, None) is not None else 0 def test_operator_summary_cache_returns_copy_with_hit_metadata() -> None: clear_operator_summary_cache() key = {"project_id": "awoooi", "limit": 30} stored = store_operator_summary( "truth_chain_quality_summary", key, {"evaluated_total": 30, "nested": {"ok": True}}, ttl_seconds=30, now_monotonic=100.0, now_utc=datetime(2026, 6, 1, tzinfo=UTC), ) assert stored["cache"]["status"] == "miss" stored["nested"]["ok"] = False cached = get_cached_operator_summary( "truth_chain_quality_summary", key, ttl_seconds=30, now_monotonic=105.5, ) assert cached is not None assert cached["cache"]["status"] == "hit" assert cached["cache"]["age_seconds"] == 5.5 assert cached["nested"]["ok"] is True def test_operator_summary_cache_expires_by_ttl() -> None: clear_operator_summary_cache() key = {"project_id": "awoooi", "page": 1} store_operator_summary( "callback_replies", key, {"total": 4}, ttl_seconds=20, now_monotonic=200.0, now_utc=datetime(2026, 6, 1, tzinfo=UTC), ) @pytest.mark.asyncio async def test_operator_summary_cache_uses_shared_redis(monkeypatch) -> None: clear_operator_summary_cache() fake_redis = _FakeRedis() monkeypatch.setattr("src.core.redis_client.get_redis", lambda: fake_redis) key = {"project_id": "awoooi", "per_page": 1} stored = await store_operator_summary_async( "callback_replies", key, {"total": 4, "items": []}, ttl_seconds=20, now_monotonic=300.0, now_utc=datetime(2026, 6, 1, tzinfo=UTC), ) assert stored["cache"]["status"] == "miss" assert fake_redis.values clear_operator_summary_cache() cached = await get_cached_operator_summary_async( "callback_replies", key, ttl_seconds=20, now_monotonic=302.0, ) assert cached is not None assert cached["cache"]["status"] == "hit" assert cached["total"] == 4 assert ( get_cached_operator_summary( "callback_replies", key, ttl_seconds=20, now_monotonic=220.0, ) is None )