T-06: Remove AppState Protocol, use ApplicationState directly

The AppState Protocol (lines 42-54) and ApplicationContext dataclass
(lines 57-69) described identical fields, creating maintenance burden.
The Protocol was only used for a single cast() in _build_app_context.

Changes:
- Remove AppState Protocol class
- Import ApplicationState from runtime_state.py
- Replace cast('AppState', request.app.state) with
  cast(ApplicationState, request.app.state)
- Remove unused Protocol import

This eliminates the redundancy while maintaining the same typing
guarantees. request.app.state is set to ApplicationState instances
during app initialization in main.py.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-25 18:25:56 +02:00
parent e57d19fd76
commit 24f9fdd358

View File

@@ -9,7 +9,7 @@ directly — to keep coupling explicit and testable.
import datetime import datetime
from collections.abc import AsyncGenerator from collections.abc import AsyncGenerator
from dataclasses import dataclass from dataclasses import dataclass
from typing import Annotated, Protocol, cast from typing import Annotated, cast
import aiohttp import aiohttp
import aiosqlite import aiosqlite
@@ -33,27 +33,12 @@ from app.repositories.protocols import (
) )
from app.services.geo_cache import GeoCache from app.services.geo_cache import GeoCache
from app.utils.constants import SESSION_COOKIE_NAME from app.utils.constants import SESSION_COOKIE_NAME
from app.utils.runtime_state import RuntimeState from app.utils.runtime_state import ApplicationState, RuntimeState
from app.utils.session_cache import NoOpSessionCache, SessionCache from app.utils.session_cache import NoOpSessionCache, SessionCache
log: structlog.stdlib.BoundLogger = structlog.get_logger() log: structlog.stdlib.BoundLogger = structlog.get_logger()
class AppState(Protocol):
"""Partial view of the FastAPI application state used by dependencies."""
settings: Settings
http_session: aiohttp.ClientSession
scheduler: AsyncIOScheduler
server_status: ServerStatus
pending_recovery: PendingRecovery | None
last_activation: dict[str, datetime.datetime] | None
runtime_settings: Settings | None
runtime_state: RuntimeState
session_cache: SessionCache
geo_cache: GeoCache # noqa: F821
@dataclass @dataclass
class ApplicationContext: class ApplicationContext:
"""A typed wrapper around shared application lifecycle resources.""" """A typed wrapper around shared application lifecycle resources."""
@@ -87,7 +72,7 @@ def _session_cache_enabled(settings: Settings) -> bool:
def _build_app_context(request: Request) -> ApplicationContext: def _build_app_context(request: Request) -> ApplicationContext:
state = cast("AppState", request.app.state) state = cast(ApplicationState, request.app.state)
session_cache = getattr(state, "session_cache", None) session_cache = getattr(state, "session_cache", None)
if session_cache is None: if session_cache is None:
session_cache = NoOpSessionCache() session_cache = NoOpSessionCache()