fix(byoa): back off on a clean wake-stream EOF instead of reconnect-spinning (#30)
Both wake-stream reconnect loops — AgentRunner.streamLoop in the BYOA daemon and
pod-agent's connect loop — kept their only sleep inside `catch`. But a
wake-stream can end CLEANLY: wake-bus's backpressure guard calls `res.end()` on
a subscriber whose socket is backed up, and any edge in front of the API can
terminate a chunked 200 the same way. Then `fetch` resolves ok, parseSseStream
RETURNS instead of throwing, and the loop falls straight back to its head and
re-fetches with zero delay.
Measured against a server that accepts the stream and immediately ends it, using
the repo's own parseSseStream:
before: 47,283 connects in 3.0s = 15,761/s, total slept 0ms
after: 2 connects in 3.0s, total slept 3000ms, ladder grown to 4000ms
Every one of those passes also re-fires kickTurn('reconnect-catchup'), and each
sets pendingRerun so runTurn keeps re-looping. From the operator's side it is a
pegged CPU and a saturated uplink; from the server's, one laptop hammering
/runtime/wake-stream.
The second half is that the ladder was reset the moment a connect returned 200
(backoff = 1000 / backoffMs = 500 inside the try). Even with a sleep added, a
200-then-EOF endpoint would reset the delay on every pass and it could never
grow. So reset only after a connection that actually STAYED UP — merely
connecting is not evidence of health.
Both loops now share one tail: log, then sleep, then double, with the reset
gated on wakeStreamWasStable(). A clean close is also logged now; it used to be
completely silent in the daemon, which is why a spinning daemon showed nothing
but a flood of "wake-stream connected" lines.
The predicate lives in sse-parse.ts, which both loops already import, and is
unit-tested there. The loop bodies themselves do network I/O and have no harness
today; the numbers above come from driving the real parseSseStream against a
local 200-then-EOF server. X
Xialie Zhuang committed
9b9b60a531fe1658a1ecb1824a58b6cfbb7fa42b
Parent: 6369874
Committed by GitHub <noreply@github.com>
on 8/19/2026, 8:02:42 PM