Repository navigation
[Serve] Wait for cancelled queue length probes before routing - #67138
pardeep-singh wants to merge 7 commits into
Conversation
Cancelled get_queue_len probes are now awaited, bounded by the max queue length response deadline, so a probe that is still handling its cancellation can't outlive the routing decision. Cancellation of the caller still propagates. Signed-off-by: Pardeep Singh <pardeep.shergill17@gmail.com>
There was a problem hiding this comment.
Code Review
This pull request improves task cancellation handling in _probe_queue_lens by ensuring unfinished probe tasks are cancelled, their exceptions are retrieved to prevent "never retrieved" logs, and the router waits for them to finish up to a maximum deadline. It also adds comprehensive unit tests to verify these cancellation behaviors. The feedback suggests improving the readability of the done callback lambda by using an explicit conditional expression instead of the or operator.
Signed-off-by: Pardeep Singh <pardeep.shergill17@gmail.com>
|
Cancelling only the unfinished probes means a probe that has already failed when the routing task is cancelled (its request was cancelled or fulfilled by another task) never has its exception retrieved, so asyncio logs "Task exception was never retrieved". Let's keep master's loop that cancels every task, since The new wait also runs before |
…ults Keep master's loop that cancels every queue length probe, so a probe that already raised doesn't have its exception logged as never retrieved. Wait for the cancelled probes only after the results in hand are processed, so a cancellation during that wait doesn't drop them, and a cancelled routing task exits without waiting. Signed-off-by: Pardeep Singh <pardeep.shergill17@gmail.com>
|
Thanks, both points were right. Fixed in fc45510:
New tests, all three failing on the previous commit:
|
|
Thanks, both points are fixed. A few more comments:
|
…errors - Wait for cancelled probes up to the round's queue_len_response_deadline_s instead of the max deadline, and document that probes should handle cancellation promptly. - Log an exception a cancelled probe raises while finishing instead of dropping it, and test it. - Assert the elapsed routing time in the slow-to-cancel test. Signed-off-by: Pardeep Singh <pardeep.shergill17@gmail.com>
|
@johntaylor-cell thanks for the second pass. Pushed e8c0060:
|
|
@pardeep-singh Thanks, 2, 3 and 4 look good. A few more should do it:
|
…obe tests State the cancel-promptly rule on RunningReplica.get_queue_len and test its cancel path against an actor. The cancel-during-wait tests now assert the task exits well under the wait's bound, the slow-cancel test waits a few seconds instead of 100, and the logged-error test waits for the warning itself. Signed-off-by: Pardeep Singh <pardeep.shergill17@gmail.com>
|
@johntaylor-cell thanks, all four are addressed in 9c68c98:
|
|
We are getting close @pardeep-singh. A few small ones remain.
|
The docstring now says what the router does: it cancels the probe at the response deadline or with its routing task, and the probe cancels its RPC and re-raises without awaiting the replica. The replica wrapper test's actor holds its cancellation open until the test releases it, so the test fails if get_queue_len awaits the cancelled ref. The routing-task test asserts the routing task ends cancelled. The cancel-during-wait tests use a 1s deadline. Signed-off-by: Pardeep Singh <pardeep.shergill17@gmail.com>
|
Thanks @johntaylor-cell, all four are in 0352dfb:
Locally: the router unit files pass (168), and |
|
Thanks @pardeep-singh, all four look good. Two small ones and this looks ready to me:
|
The test now checks the probe is cancelled right after one event loop turn, so a probe that awaits the cancelled ref with any timeout fails it. The docstring and test say that cancellation of the RPC is requested, since ray.cancel can't stop a call the replica is already running. Signed-off-by: Pardeep Singh <pardeep.shergill17@gmail.com>
|
Thanks @johntaylor-cell, both done in 6b2aa95:
|
|
Thanks @pardeep-singh, both look good. One last nit is that the comment in |
Description
RequestRouter._probe_queue_lens()cancels everyget_queue_lenprobe in itsfinallyblock but returns without waiting for them. Cancellation is cooperative, so a probe that handlesCancelledErrorwith async cleanup is still running after the router has dropped its result and gone on to fulfil the request or start the next attempt.This change:
finallystill cancels every probe.cancel()on a probe that already raised also keeps its exception from being logged as "Task exception was never retrieved". Unfinished probes also get a done callback that logs (and so retrieves) an exception raised while they handle the cancellation.ActorDiedError/ActorUnavailableErrorupdate the replica state.asyncio.wait, just before returning. The wait is bounded by the round's ownqueue_len_response_deadline_s, so a round takes at most twice its deadline.RunningReplica.get_queue_lenrequests cancellation of its RPC and re-raisesCancelledErrorwithout awaiting the replica, so in production the wait ends within one event loop turn. A probe that ignores cancellation for longer is logged and left behind, so it can't block routing.Related issues
Fixes #65719. The earlier PR #65720 was closed as stale; it waited only on the deadline path and without a bound.
Additional information
Tests in
test_pow_2_request_router.py, using a fake replica whoseget_queue_lendoes async cleanup when cancelled:test_cancelled_get_queue_len_finishes_before_routing: the slow-to-cancel replica's cleanup has finished by the time routing returns the other replica.test_slow_to_cancel_get_queue_len_does_not_block_routing: a probe whose cleanup takes far longer than the bound doesn't delay routing past the bound: with a 100s max deadline, routing still finishes in under 1s.test_routing_task_cancelled_while_cancelled_probe_finishes: cancelling the request while its probe is cleaning up still raisesCancelledError, and the routing task ends cancelled in well under the wait's bound.test_failed_probe_exception_retrieved_when_routing_task_cancelled: a probe that has already raised when the routing task is cancelled isn't reported as "never retrieved".test_probe_results_kept_when_cancelled_during_probe_cleanup: cancelling during the bounded wait exits in well under the bound and still evicts the replica whose probe returnedActorDiedError.test_cancelled_probe_error_is_logged: an exception a cancelled probe raises while finishing is logged as a warning and not reported as "never retrieved". The test waits for the warning itself rather than relying on the router's wait.test_cancelled_routing_task_does_not_wait_for_probe_cleanup: cancellation returns promptly while a cancelled probe is slow to clean up.The last three were added after review and each fails on the earlier version of this PR. The two cancel-during-wait tests fail if the wait holds a cancellation until its bound.
In
test_actor_replica_wrapper.py,test_get_queue_len_cancellation_cancels_rpccancelsRunningReplica.get_queue_lenagainst a real actor. The actor holds its cancellation open until the test releases it, so the test checks that the probe is cancelled after one event loop turn, without awaiting the replica, and that the cancellation request reaches the replica.Why this isn't a duplicate: the earlier PR #65720 was closed by the stale bot; no other open PR references #65719.
AI assistance: I used an AI coding assistant to write this change, its tests and this description.