Files
dify/api/services/dify_builder
Charles YaoandClaude Opus 4.8 2b4df02305 fix(dify_builder): close SSE subscription even when the response is never iterated
progress_bus.subscribe() eagerly enters the pub/sub subscription (opening a
Redis connection + starting a listener thread) BEFORE the SSE generator
exists, so the subscribe completes before the Celery advance can publish.
But the only close() lived in the generator's finally -- which Python does
not run if the generator is never started. A streaming Response dropped
before its first frame (client aborted, or an after_request/teardown error)
therefore leaked the connection + thread until process restart.

stream_advance_frames now returns a small _ClosingFrameStream wrapper whose
close() closes the subscription directly (idempotent); the WSGI server calls
close() on the response iterable even on early disconnect, so cleanup fires
regardless of iteration. The inner generator keeps its own finally for the
iterated/disconnect paths, so this is strictly additive -- no happy-path
change. All seven call sites get it unchanged.

Adds a regression test (never-iterated stream -> close() -> subscription closed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-03 08:48:23 +08:00
..
…