T-05: Remove app.state mutation from _build_app_context

Move session cache initialization from per-request _build_app_context to
startup lifespan handler. The session cache type is now decided once at app
startup based on settings, making _build_app_context pure (read-only).

Changes:
- Move cache initialization logic to new _update_session_cache() in main.py
- Call _update_session_cache() during lifespan startup to initialize cache
- Remove three if/elif/elif branches mutating state.session_cache from _build_app_context
- Add cache swap logic to set_runtime_settings() in runtime_state.py to handle
  runtime settings changes (e.g., setup wizard updates)
- Keep app.state.session_cache initialization in create_app() for test compatibility

This ensures:
- _build_app_context is pure and doesn't mutate app state on each request
- Session cache configuration decisions are centralized at startup
- Settings changes during runtime (via setup wizard) also trigger cache swap
- Cache initialization logic is isolated in one place

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-25 18:23:08 +02:00
parent d467190eb1
commit e57d19fd76
3 changed files with 41 additions and 10 deletions

View File

@@ -117,6 +117,23 @@ def _configure_logging(log_level: str) -> None:
# ---------------------------------------------------------------------------
def _update_session_cache(app: FastAPI, settings: Settings) -> None:
"""Update the session cache backend based on settings.
Replaces the current cache with InMemorySessionCache or NoOpSessionCache
depending on whether session caching is enabled and configured with a
positive TTL.
Args:
app: The :class:`fastapi.FastAPI` instance.
settings: The effective application settings.
"""
cache_enabled = settings.session_cache_enabled and settings.session_cache_ttl_seconds > 0.0
app.state.session_cache = (
InMemorySessionCache() if cache_enabled else NoOpSessionCache()
)
@asynccontextmanager
async def _lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
"""Manage the lifetime of all shared application resources.
@@ -137,6 +154,11 @@ async def _lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
app.state.http_session = http_session
app.state.scheduler = scheduler
# Ensure session cache is initialized based on effective settings.
# This cache is process-local and not cluster-safe. In multi-worker
# deployments, it should be replaced with a shared backend.
_update_session_cache(app, settings)
log.info("bangui_started")
try: