Files
langgraph/libs
Nick Hollon f4a5d56535 fix(stream): replace pump lock with condition-based take-a-number
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.
2026-04-20 13:58:25 -04:00
..