Stopping the server does not wait for a report file already being written, so its reports are lost #122

Closed
opened 2026-10-14 11:00:42 +02:00 by clawbot · 1 comment
Collaborator

When the server stops, the report buffer writes what it still holds in memory, but it does not wait for a report file write already under way: the one the periodic flush starts every minute, or the one Append starts in its own goroutine when 10 MiB are waiting. The stop returns success, the process exits 0, and the write is cut off. Its reports are lost, and a truncated .jsonl.zst file can be left in DATA_DIR, counted toward DATA_DIR_MAX_BYTES from the next start.

Where, on next at b1eefe0: backend/internal/reportbuf/reportbuf.go. The OnStop hook (line 149) closes done and calls flushLocked (line 268), which finds the buffer already drained and returns nil. Nothing waits for flushLoop (line 249) in the middle of a write, or for the goroutine Append starts (line 201).

How to see it: hold a write open with the buffer's file-created hook, as TestFileBeingWrittenIsNeverDeleted does, start a flush (or append past 10 MiB), then stop the fx app. The stop returns nil at once while the file is still being written.

What is right: README.md, Deployment: the image "Writes buffered reports to disk on docker stop". TODO.md, 2026-09-21: buffered reports are flushed to disk on SIGTERM. #23: a failed final flush makes the process exit non-zero instead of losing reports silently.

Severity: low. A stop has to land during a write, which is rare, but the reports are then lost with no sign of it.

Definition of done

  • Stopping the buffer returns only once every report file write already under way has ended, and the stop fails if one of them failed, as it does for a failed final flush.
  • A test holds the periodic write open, stops the app, and finds the stop still waiting until the write is released; a second test does the same for the write started at 10 MiB.
  • TODO.md updated in the same commit; commit title ends (closes #N).

Model: opus-5-5

When the server stops, the report buffer writes what it still holds in memory, but it does not wait for a report file write already under way: the one the periodic flush starts every minute, or the one `Append` starts in its own goroutine when 10 MiB are waiting. The stop returns success, the process exits 0, and the write is cut off. Its reports are lost, and a truncated `.jsonl.zst` file can be left in `DATA_DIR`, counted toward `DATA_DIR_MAX_BYTES` from the next start. **Where**, on `next` at `b1eefe0`: `backend/internal/reportbuf/reportbuf.go`. The `OnStop` hook (line 149) closes `done` and calls `flushLocked` (line 268), which finds the buffer already drained and returns nil. Nothing waits for `flushLoop` (line 249) in the middle of a write, or for the goroutine `Append` starts (line 201). **How to see it**: hold a write open with the buffer's file-created hook, as `TestFileBeingWrittenIsNeverDeleted` does, start a flush (or append past 10 MiB), then stop the fx app. The stop returns nil at once while the file is still being written. **What is right**: `README.md`, Deployment: the image "Writes buffered reports to disk on `docker stop`". `TODO.md`, 2026-09-21: buffered reports are flushed to disk on `SIGTERM`. https://git.eeqj.de/sneak/netwatch/issues/23: a failed final flush makes the process exit non-zero instead of losing reports silently. **Severity**: low. A stop has to land during a write, which is rare, but the reports are then lost with no sign of it. ## Definition of done - [ ] Stopping the buffer returns only once every report file write already under way has ended, and the stop fails if one of them failed, as it does for a failed final flush. - [ ] A test holds the periodic write open, stops the app, and finds the stop still waiting until the write is released; a second test does the same for the write started at 10 MiB. - [ ] `TODO.md` updated in the same commit; commit title ends ` (closes #N)`. Model: opus-5-5
clawbot self-assigned this 2026-10-14 11:00:42 +02:00
Author
Collaborator

Built in #138: stopping the server now waits for a report file write already under way, the periodic flush's or the one started at 10 MiB, before the final flush. A write under way that fails puts its reports back in memory (since #130), so the final flush writes them; the stop fails, exiting non-zero, only if that flush fails too.

Model: opus-5-5

Built in https://git.eeqj.de/sneak/netwatch/pulls/138: stopping the server now waits for a report file write already under way, the periodic flush's or the one started at 10 MiB, before the final flush. A write under way that fails puts its reports back in memory (since https://git.eeqj.de/sneak/netwatch/pulls/130), so the final flush writes them; the stop fails, exiting non-zero, only if that flush fails too. Model: opus-5-5
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/netwatch#122