feat(BA-6894): implement network timeout idle checker#12878
Conversation
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ons_batch Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds reconciler-based network timeout checking for interactive sessions using Valkey activity signals.
Changes:
- Implements configurable network-idle judgments.
- Adds batched active-connection counting.
- Wires Valkey dependencies and adds tests.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
tests/unit/manager/sokovan/idle_check/test_stage.py |
Updates stage dependency tests. |
tests/unit/manager/sokovan/idle_check/test_session_lifetime_checker.py |
Updates network spec fixture. |
tests/unit/manager/sokovan/idle_check/test_network_timeout_checker.py |
Tests timeout judgments and validation. |
tests/unit/manager/sokovan/idle_check/test_handler.py |
Updates handler fixtures. |
tests/unit/manager/repositories/idle_checker/test_repository.py |
Updates persisted test specification. |
tests/unit/manager/dependencies/orchestration/test_sokovan.py |
Supplies Valkey live dependency. |
tests/unit/manager/dependencies/orchestration/test_composer.py |
Updates orchestration composition tests. |
tests/unit/common/clients/valkey_client/test_valkey_live_client.py |
Tests batched connection counts. |
src/ai/backend/manager/sokovan/stages/idle_check.py |
Registers the network checker. |
src/ai/backend/manager/sokovan/stages/factory.py |
Passes Valkey into the stage. |
src/ai/backend/manager/sokovan/idle_check/checkers/network_timeout.py |
Implements network-idle evaluation. |
src/ai/backend/manager/dependencies/orchestration/sokovan.py |
Adds orchestrator Valkey input. |
src/ai/backend/manager/dependencies/orchestration/composer.py |
Propagates Valkey through orchestration. |
src/ai/backend/manager/dependencies/composer.py |
Supplies infrastructure Valkey client. |
src/ai/backend/common/data/idle_checker/types.py |
Defines network timeout configuration. |
src/ai/backend/common/clients/valkey_client/valkey_live/client.py |
Adds batched connection counting. |
changes/12878.feature.md |
Adds the feature changelog entry. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| self._valkey_live.count_active_connections_batch([ | ||
| str(session_id) for session_id in session_ids | ||
| ]), |
| if state.last_access is None: | ||
| continue |
| # Fetch session states in one batch to avoid repeated I/O per assignment. | ||
| sessions: list[IdleCheckSession] = [] | ||
| for assignment in assignments: | ||
| sessions.extend(assignment.sessions) | ||
| states = await self._prepare_states(sessions) | ||
|
|
||
| # Judge each assignment in one pass, using the pre-fetched states. | ||
| judgments: list[IdleJudgment] = [] | ||
| for assignment in assignments: | ||
| network_spec = assignment.definition.spec.network | ||
| if network_spec is None: | ||
| log.error( | ||
| "Network timeout checker {} has mismatched spec type: {}", | ||
| assignment.definition.checker_id, | ||
| assignment.definition.spec.type, | ||
| ) | ||
| continue | ||
| # Skip sessions with no timeout configured (0 means "never idle"). | ||
| if network_spec.idle_timeout_seconds == 0: | ||
| continue | ||
| idle_timeout_seconds = Decimal(network_spec.idle_timeout_seconds) |
| if state.last_access is None: | ||
| continue | ||
| current_time = Decimal(str(context.current_time.timestamp())) | ||
| idle_seconds = (current_time - state.last_access).normalize() |
There was a problem hiding this comment.
Are current_time and last_access from the same source?
There was a problem hiding this comment.
"current time" is injected by the idle checker, and "last_access" is the value stored in valkey.
| last_access_values, active_connection_counts = await asyncio.gather( | ||
| self._valkey_live.get_multiple_live_data([ | ||
| f"session.{session_id}.last_access" for session_id in session_ids | ||
| ]), | ||
| self._valkey_live.count_active_connections_batch(session_ids), | ||
| ) |
There was a problem hiding this comment.
Are they grouped for concurrent query?
There was a problem hiding this comment.
Could have run the queries separately, but I used gather because we thought running them simultaneously would yield slightly higher accuracy. It’s not required, so we can run them separately if you prefer.
Summary
NetworkTimeoutCheckerto the sokovan reconciler idle-check stage: judges interactive sessions idle when they have no active app connections and the last network access exceeds the configured timeout.NetworkTimeoutSpec.idle_timeout_seconds(0 disables the checker definition) and register the checker via DI (valkey_livewired through orchestration composers tobuild_idle_check_stage).ValkeyLiveClient.count_active_connections_batchto fetch per-session connection counts in a single batch alongside batched last-access reads.Test plan
pants testontest_network_timeout_checker.py,test_stage.py,test_valkey_live_client.py(checker judgments, DI wiring, batch count against real Valkey)pants fmt/lint/checkon changed filesResolves BA-6894
🤖 Generated with Claude Code