mirror of
https://github.com/langgenius/dify.git
synced 2026-10-04 13:47:55 +08:00
Two defects, both introduced by the streaming switch in 3838db8aa7, which
together livelocked every Builder test run.
1. Self-deadlock. run_draft executes inside the Celery task
dify_builder_advance_task.advance_session. Streaming mode does not run
the workflow in place: it enqueues workflow_based_app_execution_task
via delay() on first subscribe (app_generate_service.py:322-324) and
returns a Redis subscription. The advance task then blocked on events
from a task needing the worker slot the advance task was holding.
Observed live: advance_session "succeeded in 300.59s" (the idle
timeout) four times over, while each workflow_run finished in under 2s.
Deadlocks every time at worker concurrency 1, and as soon as N test
runs are in flight at concurrency N.
2. Lost outcome. Blocking mode returns a Mapping
{"task_id", "workflow_run_id", "data"}, but the rewrite consumed the
response with `for chunk in response`, which walks a dict's KEYS as
strings. Probed against the real service: 3 chunks, 0 run-id matches,
0 terminal matches. So every run was recorded status="running" with an
empty dify_run_id, and the "running" branch bounced the user back to
build.execution -- forever. The pre-3838db8aa7 code read
response["data"] directly; the rewrite dropped that path.
Blocking mode restored, Mapping responses handled, and the shared tail
factored into _finish_run so the two paths cannot disagree about an
outcome. The stream-consumption path is kept and still tested, for a
future consumer that is NOT a worker -- which is what live per-node
streaming to the frontend will require.
Verified end to end on a local stack: one test run, status succeeded with
a real run id, advance_session 0.04-31.8s, and the session reaching
build.review instead of looping.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>