Refactor: Move module-level mutable flags to JailServiceState

TASK-004: Replace module-level mutable runtime flags in service layer with
injected state holder, eliminating hidden global state and improving testability
and synchronization boundaries.

Changes:
- Create JailServiceState dataclass in app/utils/runtime_state.py to hold
  backend capability cache and synchronization lock
- Add JailServiceState as a field in RuntimeState (with default_factory)
- Remove module-level _backend_cmd_supported and _backend_cmd_lock from
  jail_service.py
- Refactor _check_backend_cmd_supported() to accept state parameter
- Inject JailServiceState into list_jails() and _fetch_jail_summary() via
  parameters
- Add get_jail_service_state() dependency provider in app/dependencies.py
- Add JailServiceStateDep type alias for router injection
- Update jails router to receive and pass state to service functions
- Update all tests to use jail_service_state fixture and pass state to functions
- Remove duplicate _MAX_PAGE_SIZE constant definition
- Document mutable state management in Backend-Development.md
- Update Architecture.md to describe JailServiceState and state nesting pattern

Benefits:
- Eliminates global mutable state and associated race conditions
- Makes state visible to callers (not hidden in module scope)
- Enables test isolation (each test gets fresh state)
- Prepares codebase for multi-worker deployments (state can be extracted to
  shared backend)
- Synchronization boundaries are now explicit (state.get_backend_cmd_lock())

Compliance:
- All tests pass (17 passed in TestListJails, TestGetJail, TestLockInitialization)
- No ruff linting errors
- Type-safe: JailServiceState properly typed with asyncio.Lock, bool | None

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-04-27 18:42:52 +02:00
parent 79112c0430
commit 2e221f6852
8 changed files with 157 additions and 102 deletions

View File

@@ -1,23 +1,3 @@
## 3) Blocklist import flow mixes too many responsibilities
- Where found:
- [backend/app/services/blocklist_service.py](backend/app/services/blocklist_service.py)
- Why this is needed:
- One function handling download, validation, persistence, and banning is hard to test and evolve.
- Goal:
- Split into focused components with clear boundaries.
- What to do:
- Extract downloader, parser/validator, ban executor, and persistence coordinator.
- Keep orchestration in a thin workflow service.
- Possible traps and issues:
- Behavior changes in retry/error aggregation during split.
- Docs changes needed:
- Add blocklist import sequence diagram and component ownership.
- Doc references:
- [Docs/Architekture.md](Docs/Architekture.md)
- [Docs/Features.md](Docs/Features.md)
---
## 4) Module-level mutable runtime flags in service layer
- Where found:
- [backend/app/services/jail_service.py](backend/app/services/jail_service.py)