Stop workers running tasks whose query is past its timeout - #150
Merged
Conversation
Workers took whatever the stream handed them and ran it, however long ago the query was submitted. The ARS and the other external callers stop waiting after ~5 minutes and the sync /query endpoint gives up around the same point, so a query that fell behind kept moving from operation to operation producing an answer nobody would receive -- taking worker slots and process-pool children from queries that could still be answered, and leaving its shepherd_brain row non-terminal until the monitor's abandoned-query reaper eventually swept it. The server now stamps each query with an absolute deadline at intake and that deadline travels with the task through every hop (wrap_up_task, handle_task_failure, _terminate_task). get_tasks checks it as a task is picked up -- on freshly delivered and reclaimed messages alike -- and when the budget is spent it skips the operation, drops the rest of the workflow and routes the query to finish_query with a TIMEOUT status. The query then ends exactly as any completed query does: terminal state in Postgres, callback rows reaped, logs saved, and whatever was gathered POSTed to the callback URL. A sync caller gets a partial response instead of waiting out its own timeout for nothing. Details: - QUERY_TIMEOUT_SEC (default 300) is the budget; 0 restores the old unbounded behavior. A client asking to wait longer via TRAPI parameters.timeout is not cut short -- the larger of the two wins. - finish_query is exempt (it *is* the wrap-up) and so is merge_message, which folds in callbacks upstream has already paid for. - Tasks carrying no deadline are never expired, so a rollout with in-flight queries is safe. - The explanation is flushed to the query's log list before the hand-off, since finish_query reads those logs into the response it delivers. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019VD7RfD8K98mhHVqWczWMC
Codecov Report❌ Patch coverage is
Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Workers took whatever the stream handed them and ran it, however long ago the query was submitted. The ARS and the other external callers stop waiting after ~5 minutes and the sync /query endpoint gives up around the same point, so a query that fell behind kept moving from operation to operation producing an answer nobody would receive -- taking worker slots and process-pool children from queries that could still be answered, and leaving its shepherd_brain row non-terminal until the monitor's abandoned-query reaper eventually swept it.
The server now stamps each query with an absolute deadline at intake and that deadline travels with the task through every hop (wrap_up_task, handle_task_failure, _terminate_task). get_tasks checks it as a task is picked up -- on freshly delivered and reclaimed messages alike -- and when the budget is spent it skips the operation, drops the rest of the workflow and routes the query to finish_query with a TIMEOUT status. The query then ends exactly as any completed query does: terminal state in Postgres, callback rows reaped, logs saved, and whatever was gathered POSTed to the callback URL. A sync caller gets a partial response instead of waiting out its own timeout for nothing.
Details:
Claude-Session: https://claude.ai/code/session_019VD7RfD8K98mhHVqWczWMC