-
Notifications
You must be signed in to change notification settings - Fork 297
fix: gracefully handle task exceptions in event consumer #383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: gracefully handle task exceptions in event consumer #383
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of Changes
Hello @onematchfox, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
This pull request addresses a specific issue where an asyncio.exceptions.CancelledError was being raised in the event consumer's task callback when attempting to retrieve an exception from a cancelled task. The change refines the condition for checking task completion and exceptions, ensuring that only truly completed and non-cancelled tasks are processed for their exceptions, thereby improving the robustness of the asynchronous task handling.
Highlights
- Graceful Exception Handling: Modified the
agent_task_callbackinevent_consumer.pyto preventasyncio.exceptions.CancelledErrorwhen checking for exceptions onasyncio.Taskobjects that have been cancelled. The logic now explicitly checks if a task isdoneand notcancelledbefore attempting to retrieve its exception.
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments or fill out our survey to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request fixes a potential CancelledError in the event consumer's task callback by checking if the task is cancelled or not done before accessing its exception. The review suggests calling cancelled and done as methods.
6c6e034 to
b7415aa
Compare
b7415aa to
783c466
Compare
🤖 I have created a release *beep* *boop* --- ## [0.3.1](v0.3.0...v0.3.1) (2025-08-13) ### Features * Add agent card as a route in rest adapter ([ba93053](ba93053)) ### Bug Fixes * gracefully handle task exceptions in event consumer ([#383](#383)) ([2508a9b](2508a9b)) * openapi working in sub-app ([#324](#324)) ([dec4b48](dec4b48)) * Pass `message_length` param in `get_task()` ([#384](#384)) ([b6796b9](b6796b9)) * relax protobuf dependency version requirement ([#381](#381)) ([0f55f55](0f55f55)) * Use HasField for simple message retrieval for grpc transport ([#380](#380)) ([3032aa6](3032aa6)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). --------- Co-authored-by: Holt Skinner <13262395+holtskinner@users.noreply.github.com>
Not exactly sure what the process is here - so feel free to let me know if I've missed anything. Mostly interested in the `a2a-sdk` update, as [`v0.3.1`](https://github.com/a2aproject/a2a-python/releases/tag/v0.3.1) contains [a fix](a2aproject/a2a-python#383) I put through to resolve context cancellation issues that have been plaguing me when testing multi-agent workflows. I did scan the release notes of both projects for breaking changes, and I don't think any of them affected this project's usage of the libraries. Ran the default set of agents locally, and everything seems to work fine. Signed-off-by: Brian Fox <878612+onematchfox@users.noreply.github.com>
) Not exactly sure what the process is here - so feel free to let me know if I've missed anything. Mostly interested in the `a2a-sdk` update, as [`v0.3.1`](https://github.com/a2aproject/a2a-python/releases/tag/v0.3.1) contains [a fix](a2aproject/a2a-python#383) I put through to resolve context cancellation issues that have been plaguing me when testing multi-agent workflows. I did scan the release notes of both projects for breaking changes, and I don't think any of them affected this project's usage of the libraries. Ran the default set of agents locally, and everything seems to work fine. Signed-off-by: Brian Fox <878612+onematchfox@users.noreply.github.com>
# Issue * Client disconnect triggered synchronous cleanup. * That awaited the producer task, effectively tying producer lifetime to the client connection. * Reconnecting with `tasks/resubscribe` would not receive further events because the producer had already been forced to finish. This behaviour no longer raises a `asyncio.exceptions.CancelledError` like claimed in #296 due to this fix: #383, but `tasks/resubscribe` still didn't behave as expected. # How it's reproduced In any streaming agent: Simply sending a (longer-running) `message/stream`, disconnecting, and then reconnecting to the task using `tasks/resubscribe` will no longer yield events, even though the task should have been still running. # Fix ## Code The fix is an one-liner. Now: * Client disconnect schedules cleanup in the background and returns immediately. * Producer continues; resubscribe taps the existing queue and receives subsequent events. * Cleanup still runs once the producer completes. ## Tests **Existing tests:** * Changed existing tests that asserted on `AgentExecutor.execute` by adding an `asyncio.Event` latch to wait until the background producer hits `execute`. **New tests:** * `test_stream_disconnect_then_resubscribe_receives_future_events` -- start streaming, disconnect, resubscribe, and confirm future events are received. * `test_on_message_send_stream_client_disconnect_triggers_background_cleanup_and_producer_continues` -- to validate that disconnecting is non-blocking, producer continues, and cleanup completes afterward. Fixes #296
Description
This callback shouldn't result in exceptions being raised. From docs on
.exception():Currently, if a task has been cancelled, exceptions are thrown. E.g. the following error was observed when used with
google-adk