Summary
Stream._runSub sets this._subRunning = true on entry and only resets it at the natural end of the loop (src/stream.js:308-358 in v0.7.0). Two exits skip the reset:
- The initial
redisSubscriptions.connect() throws (line ~315) — e.g. one DNS blip or a proxy closing the socket during connect.
- Any synchronous throw between the flag set and the loop.
After that, _subRunning stays true forever, every later subscribe() call sees "already running" and returns, and the process never delivers another stream message to any websocket subscriber — while continuing to accept connections and looking perfectly healthy. Clients complete their initial sync (served from getDoc) and then never receive another remote update.
Suggested fix
Wrap the loop in try/finally and reset the flag in finally; optionally split the subscription-client creation into a helper that clears this.redisSubscriptions and destroys the client on a failed connect so the next _runSub attempt starts clean:
async _runSub () {
if (this._subRunning) return
this._subRunning = true
try {
const redisSubscriptions = await this._getSubscriptionClient()
while (this.subs.size > 0 || this.subUpdates.size > 0) { /* unchanged */ }
} finally {
this._subRunning = false
}
}
We run this in production via a package patch and are happy to send a PR.
Summary
Stream._runSubsetsthis._subRunning = trueon entry and only resets it at the natural end of the loop (src/stream.js:308-358 in v0.7.0). Two exits skip the reset:redisSubscriptions.connect()throws (line ~315) — e.g. one DNS blip or a proxy closing the socket during connect.After that,
_subRunningstaystrueforever, every latersubscribe()call sees "already running" and returns, and the process never delivers another stream message to any websocket subscriber — while continuing to accept connections and looking perfectly healthy. Clients complete their initial sync (served fromgetDoc) and then never receive another remote update.Suggested fix
Wrap the loop in
try/finallyand reset the flag infinally; optionally split the subscription-client creation into a helper that clearsthis.redisSubscriptionsand destroys the client on a failed connect so the next_runSubattempt starts clean:We run this in production via a package patch and are happy to send a PR.