Skip to content

fix: remove blocking asyncio gather after cancelling disconnect watch…#1202

Merged
helloyongyang merged 1 commit into
mainfrom
fix-server-timeout
Jun 30, 2026
Merged

fix: remove blocking asyncio gather after cancelling disconnect watch…#1202
helloyongyang merged 1 commit into
mainfrom
fix-server-timeout

Conversation

@black-eleven

Copy link
Copy Markdown
Contributor

…er in sync endpoints

After wait_task completes, cancel() on disconnect_task followed by asyncio.gather
blocks indefinitely because the disconnect watcher is stuck in request.is_disconnected()
→ receive() which never returns while the client is still connected. Fire-and-forget
cancel is sufficient — the completed task already holds the result.

Affected: POST /v1/tasks/image/sync and OpenAI /v1/images/* sync handlers.

…er in sync endpoints

   After wait_task completes, cancel() on disconnect_task followed by asyncio.gather
   blocks indefinitely because the disconnect watcher is stuck in request.is_disconnected()
   → receive() which never returns while the client is still connected. Fire-and-forget
   cancel is sufficient — the completed task already holds the result.

   Affected: POST /v1/tasks/image/sync and OpenAI /v1/images/* sync handlers.
@helloyongyang helloyongyang merged commit 152ac49 into main Jun 30, 2026
2 checks passed
@helloyongyang helloyongyang deleted the fix-server-timeout branch June 30, 2026 08:05

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 simplifies the asynchronous task handling and cleanup logic when waiting for image generation tasks and client disconnect watchers. The reviewer identified an issue in both modified files where removing the .result() call on disconnect_task prevents exceptions raised within the disconnect watcher from being propagated. This can lead to unretrieved task exception warnings and incorrect HTTP 499 status codes instead of proper server errors. Restoring the .result() check is recommended.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +127 to 130
if disconnect_task in done:
if not wait_task.done():
wait_task.cancel()
await asyncio.wait({wait_task}, timeout=0)
raise HTTPException(status_code=499, detail=f"Client disconnected, task {task_id} cancelled")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

By checking if disconnect_task in done: without calling .result(), any exception raised inside _watch_client_disconnect (for example, if request.is_disconnected() fails) will not be propagated. This leads to two issues:

  1. Python will log a Task exception was never retrieved warning.
  2. The endpoint will incorrectly raise a 499 Client Disconnected error instead of propagating the actual exception (which would normally result in a 500/503 error).

Calling disconnect_task.result() ensures that any exceptions are properly propagated and handled.

Suggested change
if disconnect_task in done:
if not wait_task.done():
wait_task.cancel()
await asyncio.wait({wait_task}, timeout=0)
raise HTTPException(status_code=499, detail=f"Client disconnected, task {task_id} cancelled")
if disconnect_task in done and disconnect_task.result():
if not wait_task.done():
wait_task.cancel()
raise HTTPException(status_code=499, detail=f"Client disconnected, task {task_id} cancelled")

Comment on lines +158 to 161
if disconnect_task in done:
if not wait_task.done():
wait_task.cancel()
await asyncio.gather(wait_task, return_exceptions=True)
raise HTTPException(status_code=499, detail=f"Client disconnected, task {task_id} cancelled")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

By checking if disconnect_task in done: without calling .result(), any exception raised inside _watch_client_disconnect (for example, if request.is_disconnected() fails) will not be propagated. This leads to two issues:

  1. Python will log a Task exception was never retrieved warning.
  2. The endpoint will incorrectly raise a 499 Client Disconnected error instead of propagating the actual exception (which would normally result in a 500/503 error).

Calling disconnect_task.result() ensures that any exceptions are properly propagated and handled.

Suggested change
if disconnect_task in done:
if not wait_task.done():
wait_task.cancel()
await asyncio.gather(wait_task, return_exceptions=True)
raise HTTPException(status_code=499, detail=f"Client disconnected, task {task_id} cancelled")
if disconnect_task in done and disconnect_task.result():
if not wait_task.done():
wait_task.cancel()
raise HTTPException(status_code=499, detail=f"Client disconnected, task {task_id} cancelled")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants