mirror of
https://github.com/Comfy-Org/comfy-python-sdk.git
synced 2026-11-04 23:37:47 +00:00
[PR #12] [MERGED] fix: read-idle timeout on SSE so a stalled stream can't hang events() #19
Labels
No labels
audit:ai-readiness
audit:community
audit:github
audit:health-scoring
audit:policy
audit:release
audit:supply-chain
effort:medium
effort:small
effort:small
effort:trivial
priority:nice-to-have
priority:nice-to-have
priority:recommended
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Comfy-Org/comfy-python-sdk#19
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/Comfy-Org/comfy-python-sdk/pull/12
Author: @wei-hai
Created: 7/22/2026
Status: ✅ Merged
Merged: 7/22/2026
Merged by: @wei-hai
Base:
main← Head:fix/sse-idle-timeout📝 Commits (2)
157765bfix: read-idle timeout on SSE so a stalled stream can't hang events()8d217ectest: cover async SSE recovery + timeout=None opt-out📊 Changes
3 files changed (+113 additions, -10 deletions)
View changed files
📝
src/comfy_low/transport.py(+19 -6)📝
tests/conftest.py(+16 -4)➕
tests/test_sse_idle.py(+78 -0)📄 Description
Found running a real >10-minute job against prod: the SSE stream went silent at ~3 min (no frames, no keepalive, no close — a "zombie" connection), and
job.events()hung — still blocked minutes after the job had already completed.poll/wait/runwere unaffected (the job itself finished fine).Root cause
ComfyLow.get_job_events(sync + async) opened the SSE stream withtimeout=None, which disables httpx's read timeout — soiter_lines()blocks forever on a stalled-but-open connection. The high-levelJob.events()reconnect/poll-fallback only runs when the stream ends (the generator returns or raises), which never happens for a zombie →events()hangs.Fix
Give
get_job_eventsa read-idle timeout (_SSE_IDLE_TIMEOUT, well above the server's keepalive interval) by default. A stalled stream now raiseshttpx.ReadTimeout, whichJob.events()already catches and turns into a poll (terminal?) / reconnect.timeout=Nonestill available to opt out.Tests
Added a threaded stub
stallmode (sends a couple frames, then holds the socket open and silent) and a regression test assertingevents()recovers via the poll fallback in ~0.3s instead of waiting for close / hanging. Full suite: 74 passed; ruff/format/mypy/hygiene clean.🤖 Generated with Claude Code
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.