fix(api-server): count "stopping" runs as active in readiness work counts
_readiness_work_counts()'s active_api_runs set is {"queued", "running",
"waiting_for_approval"} — it excludes "stopping", the status
_handle_stop_run() sets while a run is being interrupted. Since the stop
is fully cooperative (the run stays "stopping" — doing real
executor-thread work — until the agent actually notices the interrupt and
the task settles to "cancelled", an unbounded window, not a fixed
timeout), /health/detailed's background_queues.active_api_runs
undercounts real active work for that whole duration.
Fix: add "stopping" to the active-status set. background_queues.status
itself is hardcoded "ok" (gateway/readiness.py), so this doesn't change
overall readiness — it only corrects the count value external monitoring
tooling reads from this endpoint.
This commit is contained in:
parent
eff293115d
commit
0d5982d910
|
|
@ -1071,7 +1071,13 @@ class APIServerAdapter(BasePlatformAdapter):
|
|||
active_api_runs = sum(
|
||||
1
|
||||
for status in self._run_statuses.values()
|
||||
if status.get("status") in {"queued", "running", "waiting_for_approval"}
|
||||
# "stopping" (set by _handle_stop_run) is not terminal: the run
|
||||
# stays in this state, doing real executor-thread work, until the
|
||||
# agent actually notices the interrupt and the task settles to
|
||||
# "cancelled" — an unbounded window, not the old ~5s hard-timeout
|
||||
# wait. Excluding it here undercounts active_api_runs for the
|
||||
# whole duration of a cooperative stop.
|
||||
if status.get("status") in {"queued", "running", "waiting_for_approval", "stopping"}
|
||||
)
|
||||
process_depth = 0
|
||||
active_delegations = 0
|
||||
|
|
|
|||
|
|
@ -926,6 +926,26 @@ class TestHealthDetailedEndpoint:
|
|||
patch("tools.async_delegation.active_count", return_value=2):
|
||||
assert adapter._readiness_work_counts() == (3, 4, 2)
|
||||
|
||||
def test_readiness_work_counts_include_stopping_runs(self, adapter):
|
||||
"""Regression: _handle_stop_run() sets status="stopping" and holds it
|
||||
there — cooperatively, with no hard timeout — until the agent notices
|
||||
the interrupt and the task actually exits. A run in that window is
|
||||
still doing real executor-thread work and must count as active,
|
||||
the same as "running"; excluding it undercounts active_api_runs for
|
||||
the whole (now-unbounded) cooperative-stop duration."""
|
||||
adapter._run_statuses = {
|
||||
"queued": {"status": "queued"},
|
||||
"running": {"status": "running"},
|
||||
"approval": {"status": "waiting_for_approval"},
|
||||
"stopping": {"status": "stopping"},
|
||||
"done": {"status": "completed"},
|
||||
"cancelled": {"status": "cancelled"},
|
||||
}
|
||||
|
||||
with patch("tools.process_registry.process_registry.completion_queue.qsize", return_value=0), \
|
||||
patch("tools.async_delegation.active_count", return_value=0):
|
||||
assert adapter._readiness_work_counts() == (4, 0, 0)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# /v1/models endpoint
|
||||
|
|
|
|||
Loading…
Reference in New Issue