fix(concurrency): add thread safety to InvariantService #11051

Closed
HAL9000 wants to merge 9 commits from pr_fix/8209 into master

9 Commits

Author SHA1 Message Date
drew 81db980328 test(concurrency): cover InvariantService thread safety
CI / load-versions (pull_request) Successful in 16s
CI / push-validation (pull_request) Successful in 38s
CI / lint (pull_request) Successful in 52s
CI / typecheck (pull_request) Successful in 1m13s
CI / quality (pull_request) Successful in 1m6s
CI / security (pull_request) Successful in 1m22s
CI / build (pull_request) Successful in 55s
CI / helm (pull_request) Successful in 57s
CI / unit_tests (pull_request) Successful in 6m10s
CI / docker (pull_request) Successful in 1m25s
CI / integration_tests (pull_request) Successful in 10m52s
CI / coverage (pull_request) Successful in 9m38s
CI / status-check (pull_request) Successful in 3s
2026-06-16 22:33:48 -04:00
controller-ci-rerun 8428c4dbbe chore: re-trigger CI [controller] 2026-06-16 22:23:33 -04:00
controller-ci-rerun a5cf75c6b5 chore: re-trigger CI [controller] 2026-06-16 22:23:32 -04:00
HAL9000 e61514e8d0 fix(concurrency): fix lint and Behave step conflict in thread-safety tests
- Remove unused imports (Invariant, ULID) from step definitions
- Rename ambiguous parameter l -> num_listers (E741)
- Fix import ordering in invariant_service.py (RLock before structlog)
- Fix line too long in invariant_service.py:208
- Apply ruff format to steps file
- Disambiguate @then step text that conflicted with context_tier_thread_safety_steps.py

ISSUES CLOSED: #7524
2026-06-16 22:23:32 -04:00
controller-ci-rerun b4f49239a8 chore: re-trigger CI [controller] 2026-06-16 22:23:32 -04:00
controller-ci-rerun 0595560b17 chore: re-trigger CI [controller] 2026-06-16 22:23:32 -04:00
HAL9000 5d3e8ecb0a fix(concurrency): add thread safety to InvariantService
Add threading.RLock to InvariantService to protect shared state
(_invariants dict, _enforcement_records list) from concurrent access
by multiple threads during parallel plan execution. Prevents
RuntimeError: dictionary changed size during iteration and data
corruption in multi-threaded environments.

All five public methods (add_invariant, list_invariants, remove_invariant,
get_effective_invariants, enforce_invariants) are now thread-safe via
lock acquisition. Three helper read accessors added: get_enforcement_records,
get_invariant, get_invariants_snapshot.

Includes comprehensive BDD test coverage in features/invariant_service_thread_safety.feature.

ISSUES CLOSED: #7524
2026-06-16 22:23:32 -04:00
HAL9000 fe8ac88c86 fix(concurrency): add thread safety to InvariantService (lint and Behave fixes)
Address all review feedback from HAL9001:
- Remove unused 'from typing import cast' import (F401)
- Replace unused variables with _ prefix (F841)
- Use contextlib.suppress(Exception) instead of try/except/pass (SIM105)
- Fix ScenarioOutline decorators to use curly-brace {param:d} syntax
- Convert And-Then steps to proper Then/assertion steps for Behave compatibility
- Rename branch from pr_fix/8209 to bugfix/m3-invariant-service-thread-safety

Fixes: resolves PR #11051 review comments
2026-06-16 22:23:32 -04:00
HAL9000 6914c1c30e fix(concurrency): add thread safety to InvariantService
Add threading.RLock to InvariantService to protect shared state
(_invariants dict, _enforcement_records list) from concurrent access
by multiple threads during parallel plan execution. Prevents
RuntimeError: dictionary changed size during iteration and data
corruption in multi-threaded environments.

Changes:
- Added self._lock = RLock() in __init__
- Wrapped all public methods (add_invariant, list_invariants,
  remove_invariant, get_effective_invariants, enforce_invariants)
  with lock acquisition via context managers
- Added helper read methods: get_enforcement_records(), get_invariant(),
  get_invariants_snapshot() -- all thread-safe
- Added BDD tests for concurrent access patterns
- Updated CHANGELOG.md and CONTRIBUTORS.md

ISSUES CLOSED: #7524
2026-06-16 22:23:32 -04:00