Repository navigation
fix(sender): settle sends when the loop terminates - #170
Ehsan-hash wants to merge 2 commits into
Conversation
Developed with AI assistance using Codex. Regression tests intentionally fail until the sender lifecycle fix follows.
Retain writer failures for active, queued and later sends. Preserve cancellation during shutdown and reject sends after closure, including cancellation before the sender loop starts. Developed and reviewed with AI assistance using Codex.
| self._writer.write(item.payload) | ||
| await self._writer.drain() | ||
| except asyncio.CancelledError: | ||
| self._set_terminal(ConnectionError("Sender closed"), cancel_pending=True) |
There was a problem hiding this comment.
| self._set_terminal(ConnectionError("Sender closed"), cancel_pending=True) | |
| item.future.cancel() |
It seems unnecessarily complicated, what does it do differently than this simple change?
send() needs to listen to a completeness flag of course.
There was a problem hiding this comment.
Thanks for reviewing this, @frostming. For the active send when the loop is cancelled, I agree that item.future.cancel() is sufficient.
With the terminal flag you mentioned, the remaining cases are cancelling the queued futures too, and detecting cancellation before _loop() starts (its exception handler never runs in that case, which is why there is a task-done callback). The writer-failure path separately preserves the original exception, such as BrokenPipeError, for active, queued and later sends instead of turning it into cancellation.
Those are the cases covered by the sender lifecycle regressions and the two-request connection regression. A simpler version using direct cancellation plus the terminal flag, queue cleanup and pre-start handling could preserve the same behaviour; the helper itself is not required.
There was a problem hiding this comment.
ok, then we can add the _on_task_done callback to clear all pending futures.
|
Thanks for the follow-up, @frostming. I'm closing this PR because I can't carry the proposed revision through validation and review. The patch and regression tests remain available if useful. |
Thank you, I like simplicity instead of throwing a prompt to the agent and ask it to make the CI green. Codex especially likes to make things complicated. If you look at the effect of this class as a whole, you will find that #190 can accomplish the same thing, and the problem you mentioned does not exist. |
Why
When the sender loop fails or is cancelled, concurrent requests can wait forever for a send that will never complete. Keep a terminal sender state so active, queued and later sends all finish.
What changed
Connection.Scope
Blast Radius
Changes how pending sends terminate after writer failure or shutdown. Existing peer cancellation, stdio and HTTP/WebSocket tests pass.
Verification
5 failed, 7 passed; fixed focused regressions:12 passed.75 passed.make checkpasses;make test:413 passed, 1 skippedon Python 3.12. The skipped Gemini integration was not enabled.Developed and reviewed with AI assistance using Codex. No live model/provider calls were used for validation.