fix(kanban): archive_task now kills the worker process
archive_task() was a pure DB operation — it cleared worker_pid, claim_lock, and status from the tasks row but never sent SIGTERM to the actual OS process. A running worker stayed alive until it next called kanban_complete/kanban_block and discovered it was archived, burning API quota and compute resources. Fix: snapshot pid+claim_lock before the write_txn clears them, then call _terminate_reclaimed_worker() — same function reclaim_task uses — which sends SIGTERM, waits 5s, then SIGKILL if still alive. The termination metadata is included in the 'archived' event so operators can see what happened. Order matches reclaim_task: terminate first, then DB update. For non-running / non-local tasks, _terminate_reclaimed_worker returns immediately as a no-op. Closes #33774 reprise: the scratch-workspace side was fixed in fc8afd500, but the orphaned-process side was never addressed.
This commit is contained in:
+15
-1
@@ -3495,6 +3495,18 @@ def specify_triage_task(
|
||||
|
||||
|
||||
def archive_task(conn: sqlite3.Connection, task_id: str) -> bool:
|
||||
# Snapshot pid+claim before the DB update clears them, so we can
|
||||
# terminate the worker process even after those columns are NULLed.
|
||||
row = conn.execute(
|
||||
"SELECT worker_pid, claim_lock FROM tasks WHERE id = ?",
|
||||
(task_id,),
|
||||
).fetchone()
|
||||
prev_pid = row["worker_pid"] if row else None
|
||||
prev_lock = row["claim_lock"] if row else None
|
||||
# Terminate the worker process first (same order as reclaim_task).
|
||||
# If the task wasn't running on this host, this is a safe no-op.
|
||||
termination = _terminate_reclaimed_worker(prev_pid, prev_lock)
|
||||
|
||||
with write_txn(conn):
|
||||
cur = conn.execute(
|
||||
"UPDATE tasks SET status = 'archived', "
|
||||
@@ -3508,7 +3520,9 @@ def archive_task(conn: sqlite3.Connection, task_id: str) -> bool:
|
||||
conn, task_id, outcome="reclaimed", status="reclaimed",
|
||||
summary="task archived with run still active",
|
||||
)
|
||||
_append_event(conn, task_id, "archived", None, run_id=run_id)
|
||||
payload = {}
|
||||
payload.update(termination)
|
||||
_append_event(conn, task_id, "archived", payload, run_id=run_id)
|
||||
# ``archived`` parents no longer block children; promote them now.
|
||||
recompute_ready(conn)
|
||||
# Reap the workspace on archive too (never-completed tasks kept it forever).
|
||||
|
||||
Reference in New Issue
Block a user