mirror of
https://github.com/langchain-ai/langgraph.git
synced 2026-08-24 16:42:24 +02:00
The async pump serialized `graph_aiter.__anext__()` with an `asyncio.Lock`, held across the full await. When two cursors read different projections concurrently, the "losing" task slept inside `_apump_next` on the lock itself — so when the active pumper pushed its data onto the losing task's buffer, the loser couldn't observe it until another graph event forced the lock to change hands. Each passive consumer saw its deltas one graph event late; bursts coalesced at turn boundaries instead of streaming live. Switch to an `asyncio.Condition` + `_pumping` flag. Exactly one task is the active pumper; others do `cond.wait()` and are notified after every pump step. Passive consumers wake as soon as their buffer fills, drop out of `_apump_next`, and let the iterator's buffer check yield the data. Single-consumer behavior is unchanged; multi- consumer throughput improves ~5x on bursty tools and no events are lost.