streamWithReconnect in internal/streamer/streamer.go returns, and never connects again, whenever stream returns no error, taking that to mean shutdown. But stream also returns no error when the server ends the response normally: the read loop simply reaches the end of the body. That path also skips SetConnected(false), so /.well-known/healthcheck.json keeps reporting ris_live as ok.
From then on the daemon takes in no updates and serves an ever older routing table while looking healthy, so neither the health check nor a container restart policy acts.
Failure scenario, confirmed with a throwaway test: a test server sends one line and ends the response. streamWithReconnect returns after about 1 ms having made a single request, and the connected flag is still true. The existing TestStreamDoesNotLeakTickersAcrossReconnects already relies on stream returning no error when a response body ends.
Severity: critical
Definition of done
A test, failing before the fix: against a test server that ends each response after one line, the streamer makes a second request, and the connected flag is false between the two connections.
streamWithReconnect returns only when its context is cancelled. Any other end of a connection, with or without an error, marks the stream disconnected and reconnects with the existing backoff.
make check passes.
Model: opus-5-5
`streamWithReconnect` in `internal/streamer/streamer.go` returns, and never connects again, whenever `stream` returns no error, taking that to mean shutdown. But `stream` also returns no error when the server ends the response normally: the read loop simply reaches the end of the body. That path also skips `SetConnected(false)`, so `/.well-known/healthcheck.json` keeps reporting `ris_live` as `ok`.
From then on the daemon takes in no updates and serves an ever older routing table while looking healthy, so neither the health check nor a container restart policy acts.
Failure scenario, confirmed with a throwaway test: a test server sends one line and ends the response. `streamWithReconnect` returns after about 1 ms having made a single request, and the connected flag is still true. The existing `TestStreamDoesNotLeakTickersAcrossReconnects` already relies on `stream` returning no error when a response body ends.
Severity: critical
## Definition of done
- A test, failing before the fix: against a test server that ends each response after one line, the streamer makes a second request, and the connected flag is false between the two connections.
- `streamWithReconnect` returns only when its context is cancelled. Any other end of a connection, with or without an error, marks the stream disconnected and reconnects with the existing backoff.
- `make check` passes.
Model: opus-5-5
clawbot
self-assigned this 2026-10-14 14:50:29 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
streamWithReconnectininternal/streamer/streamer.goreturns, and never connects again, wheneverstreamreturns no error, taking that to mean shutdown. Butstreamalso returns no error when the server ends the response normally: the read loop simply reaches the end of the body. That path also skipsSetConnected(false), so/.well-known/healthcheck.jsonkeeps reportingris_liveasok.From then on the daemon takes in no updates and serves an ever older routing table while looking healthy, so neither the health check nor a container restart policy acts.
Failure scenario, confirmed with a throwaway test: a test server sends one line and ends the response.
streamWithReconnectreturns after about 1 ms having made a single request, and the connected flag is still true. The existingTestStreamDoesNotLeakTickersAcrossReconnectsalready relies onstreamreturning no error when a response body ends.Severity: critical
Definition of done
streamWithReconnectreturns only when its context is cancelled. Any other end of a connection, with or without an error, marks the stream disconnected and reconnects with the existing backoff.make checkpasses.Model: opus-5-5
Duplicate of #53, filed in error by a parallel review; closing.
Model: opus-5-5