Coverage for src/lexigram/web/integrations/cache.py: 40%
25 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 04:37 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 04:37 +0800
1"""Cache integration — attaches Redis client to ASGI app state for lifespan cleanup."""
3from __future__ import annotations
5from typing import TYPE_CHECKING
7from lexigram.contracts.core.di import ContainerResolverProtocol
8from lexigram.contracts.exceptions import UnresolvableDependencyError
9from lexigram.contracts.infra.cache import CacheBackendProtocol
10from lexigram.logging import get_logger
12if TYPE_CHECKING:
13 from starlette.applications import Starlette
15logger = get_logger(__name__)
18class CacheIntegration:
19 """Resolves the cache backend and attaches Redis client to app.state.
21 Optional integration: silently skips if no cache module is registered
22 or if the backend doesn't expose an underlying Redis client (e.g., memory backend).
23 """
25 @staticmethod
26 async def configure(
27 app: Starlette,
28 container: ContainerResolverProtocol,
29 ) -> None:
30 """Attach the Redis client to app.state.redis_client.
32 Args:
33 app: The ASGI application.
34 container: The DI container resolver.
36 Note:
37 This integration only attaches the client for Redis backends.
38 Memory backends don't have an underlying client and are skipped.
39 """
40 try:
41 cache = await container.resolve(CacheBackendProtocol)
42 except (LookupError, UnresolvableDependencyError, ValueError):
43 logger.debug("No cache module registered; CacheIntegration skipped")
44 return
46 if cache is None:
47 logger.debug("No cache module registered; CacheIntegration skipped")
48 return
50 if hasattr(cache, "get_underlying_client"):
51 client = cache.get_underlying_client()
52 if client is not None:
53 app.state.redis_client = client
54 logger.info("CacheIntegration: redis_client attached to app.state")
55 else:
56 logger.debug(
57 "Cache backend has no underlying client (memory backend?); "
58 "CacheIntegration skipped"
59 )
60 else:
61 logger.debug(
62 "Cache backend doesn't expose get_underlying_client; "
63 "CacheIntegration skipped"
64 )