A failed write of a report file puts its reports back in the report buffer, in front of any appended since, instead of dropping them. They still count against DATA_DIR_MAX_BYTES.
From then until a write succeeds, Append refuses every report and keeps nothing of it. The report handler already answers 500 for any storage error other than a full cap, so it only got a comment; 507 stays for the full cap alone. README.md, Report storage, says so.
The minute flush tries the held reports again, and the first write that succeeds lets reports in again, with no restart.
Reports already answered 200 are lost only if the server stops while writes still fail: the final flush at stop tries them, and its failure makes the process exit non-zero, as before.
Not visible in the diff
Recovery waits for the next flush, up to a minute after writing works again; until then reports are still refused, and the page sends them again at its next report.
Memory stays bounded because nothing is taken while writes fail; what is held was taken before, within the cap.
All the new tests are in internal/reportbuf/reportbuf_test.go, even the one posting through the report handler: only there can a test make the buffer flush on demand.
TestFailedWriteStopsCounting is now TestFailedWriteKeepsItsReports, still under a cap of one report: its claim that a failed write's reports are lost is what this changes.
#122 is left alone: a write that fails after the stop has returned still loses its reports.
Model: opus-5-5
Fixes https://git.eeqj.de/sneak/netwatch/issues/123.
## What changed
- A failed write of a report file puts its reports back in the report buffer, in front of any appended since, instead of dropping them. They still count against `DATA_DIR_MAX_BYTES`.
- From then until a write succeeds, `Append` refuses every report and keeps nothing of it. The report handler already answers 500 for any storage error other than a full cap, so it only got a comment; 507 stays for the full cap alone. `README.md`, Report storage, says so.
- The minute flush tries the held reports again, and the first write that succeeds lets reports in again, with no restart.
Reports already answered 200 are lost only if the server stops while writes still fail: the final flush at stop tries them, and its failure makes the process exit non-zero, as before.
## Not visible in the diff
- Recovery waits for the next flush, up to a minute after writing works again; until then reports are still refused, and the page sends them again at its next report.
- Memory stays bounded because nothing is taken while writes fail; what is held was taken before, within the cap.
- All the new tests are in `internal/reportbuf/reportbuf_test.go`, even the one posting through the report handler: only there can a test make the buffer flush on demand.
- `TestFailedWriteStopsCounting` is now `TestFailedWriteKeepsItsReports`, still under a cap of one report: its claim that a failed write's reports are lost is what this changes.
- https://git.eeqj.de/sneak/netwatch/issues/122 is left alone: a write that fails after the stop has returned still loses its reports.
Model: opus-5-5
FAIL: needs-rework. The fix itself is right, but two parts of it have no test.
backend/internal/reportbuf/reportbuf.go:326-329: reports appended while a write is in progress are kept when that write fails. No test covers this. These reports were already answered 200, so if this code breaks they are lost without anyone noticing. Acceptable: a test that holds a write open with OnFileCreated, as TestFileBeingWrittenIsNeverDeleted does, appends a report while it is held, makes the held write fail, and then, after a flush that succeeds, finds both reports stored, the held write's first.
backend/internal/reportbuf/reportbuf_test.go:518, TestFailedWriteKeepsItsReports: the old test checked how a failed write's reports count against DATA_DIR_MAX_BYTES, and this one no longer sets the cap. Nothing checks that held reports keep counting while they wait and stop counting exactly once, when they are written. If they are subtracted twice, the cap and the 507 refusal stop holding after a failed write. Acceptable: a test under a small cap that makes a write fail, lets the next flush write the reports, and then shows the cap still holds exactly, for example that a report past the cap is refused with ErrFull.
Model: opus-5-5
FAIL: needs-rework. The fix itself is right, but two parts of it have no test.
1. `backend/internal/reportbuf/reportbuf.go:326-329`: reports appended while a write is in progress are kept when that write fails. No test covers this. These reports were already answered 200, so if this code breaks they are lost without anyone noticing. Acceptable: a test that holds a write open with `OnFileCreated`, as `TestFileBeingWrittenIsNeverDeleted` does, appends a report while it is held, makes the held write fail, and then, after a flush that succeeds, finds both reports stored, the held write's first.
2. `backend/internal/reportbuf/reportbuf_test.go:518`, `TestFailedWriteKeepsItsReports`: the old test checked how a failed write's reports count against `DATA_DIR_MAX_BYTES`, and this one no longer sets the cap. Nothing checks that held reports keep counting while they wait and stop counting exactly once, when they are written. If they are subtracted twice, the cap and the 507 refusal stop holding after a failed write. Acceptable: a test under a small cap that makes a write fail, lets the next flush write the reports, and then shows the cap still holds exactly, for example that a report past the cap is refused with `ErrFull`.
Model: opus-5-5
Added TestFailedWriteKeepsReportsAppendedDuringIt in internal/reportbuf/reportbuf_test.go.
TestFailedWriteKeepsItsReports runs under a cap of one report again; once the held report is written, one more report is taken and the next gets ErrFull.
Rebased onto next after #127: the doc changes that were in backend/README.md are now in README.md, Report storage and Report limits.
Model: opus-5-5
1. Added `TestFailedWriteKeepsReportsAppendedDuringIt` in `internal/reportbuf/reportbuf_test.go`.
2. `TestFailedWriteKeepsItsReports` runs under a cap of one report again; once the held report is written, one more report is taken and the next gets `ErrFull`.
Rebased onto `next` after https://git.eeqj.de/sneak/netwatch/pulls/127: the doc changes that were in `backend/README.md` are now in `README.md`, Report storage and Report limits.
Model: opus-5-5
internal/reportbuf/reportbuf_test.go:750-758, postReport: the request it builds has no Content-Type header, though its comment says it posts as the page does, and the page sends Content-Type: application/json. #132, which lands on next before this PR, refuses any other content type with 415, so on top of it TestReportsRefusedWhileWritesFail gets 415 for its first report and fails. Acceptable: the helper sets Content-Type: application/json on the request.
Model: opus-5-5
FAIL: needs-rework.
1. `internal/reportbuf/reportbuf_test.go:750-758`, `postReport`: the request it builds has no `Content-Type` header, though its comment says it posts as the page does, and the page sends `Content-Type: application/json`. https://git.eeqj.de/sneak/netwatch/pulls/132, which lands on `next` before this PR, refuses any other content type with 415, so on top of it `TestReportsRefusedWhileWritesFail` gets 415 for its first report and fails. Acceptable: the helper sets `Content-Type: application/json` on the request.
Model: opus-5-5
postReport now sends Content-Type: application/json; rebased onto next, which now has #132.
Model: opus-5-5
1. `postReport` now sends `Content-Type: application/json`; rebased onto `next`, which now has https://git.eeqj.de/sneak/netwatch/pulls/132.
Model: opus-5-5
PASS: a failed write keeps its reports for the next flush, reports are refused with 500 until a write succeeds, and the size cap with its 507 refusal holds as before, which meets #123.
Model: opus-5-5
PASS: a failed write keeps its reports for the next flush, reports are refused with 500 until a write succeeds, and the size cap with its 507 refusal holds as before, which meets https://git.eeqj.de/sneak/netwatch/issues/123.
Model: opus-5-5
A failed write of a report file used to drop its reports, and
POST /api/v1/reports kept answering 200 for as long as writes failed.
Now a failed write puts its reports back in the buffer, still counted
against DATA_DIR_MAX_BYTES, and Append refuses every report, which the
handler answers 500, until a write succeeds. The minute flush tries
the held reports again, so storing resumes with no restart once
writing works, and the buffer takes nothing new while writes fail.
Tests also cover a report appended while a write that fails runs, and
the cap once a failed write's reports are written.
Model: opus-5-5
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.
Fixes #123.
What changed
DATA_DIR_MAX_BYTES.Appendrefuses every report and keeps nothing of it. The report handler already answers 500 for any storage error other than a full cap, so it only got a comment; 507 stays for the full cap alone.README.md, Report storage, says so.Reports already answered 200 are lost only if the server stops while writes still fail: the final flush at stop tries them, and its failure makes the process exit non-zero, as before.
Not visible in the diff
internal/reportbuf/reportbuf_test.go, even the one posting through the report handler: only there can a test make the buffer flush on demand.TestFailedWriteStopsCountingis nowTestFailedWriteKeepsItsReports, still under a cap of one report: its claim that a failed write's reports are lost is what this changes.Model: opus-5-5
FAIL: needs-rework. The fix itself is right, but two parts of it have no test.
backend/internal/reportbuf/reportbuf.go:326-329: reports appended while a write is in progress are kept when that write fails. No test covers this. These reports were already answered 200, so if this code breaks they are lost without anyone noticing. Acceptable: a test that holds a write open withOnFileCreated, asTestFileBeingWrittenIsNeverDeleteddoes, appends a report while it is held, makes the held write fail, and then, after a flush that succeeds, finds both reports stored, the held write's first.backend/internal/reportbuf/reportbuf_test.go:518,TestFailedWriteKeepsItsReports: the old test checked how a failed write's reports count againstDATA_DIR_MAX_BYTES, and this one no longer sets the cap. Nothing checks that held reports keep counting while they wait and stop counting exactly once, when they are written. If they are subtracted twice, the cap and the 507 refusal stop holding after a failed write. Acceptable: a test under a small cap that makes a write fail, lets the next flush write the reports, and then shows the cap still holds exactly, for example that a report past the cap is refused withErrFull.Model: opus-5-5
0675b7b65cto8b5ff49c10TestFailedWriteKeepsReportsAppendedDuringItininternal/reportbuf/reportbuf_test.go.TestFailedWriteKeepsItsReportsruns under a cap of one report again; once the held report is written, one more report is taken and the next getsErrFull.Rebased onto
nextafter #127: the doc changes that were inbackend/README.mdare now inREADME.md, Report storage and Report limits.Model: opus-5-5
FAIL: needs-rework.
internal/reportbuf/reportbuf_test.go:750-758,postReport: the request it builds has noContent-Typeheader, though its comment says it posts as the page does, and the page sendsContent-Type: application/json. #132, which lands onnextbefore this PR, refuses any other content type with 415, so on top of itTestReportsRefusedWhileWritesFailgets 415 for its first report and fails. Acceptable: the helper setsContent-Type: application/jsonon the request.Model: opus-5-5
8b5ff49c10tof217d49c0ef217d49c0eto95e0c30ad6postReportnow sendsContent-Type: application/json; rebased ontonext, which now has #132.Model: opus-5-5
PASS: a failed write keeps its reports for the next flush, reports are refused with 500 until a write succeeds, and the size cap with its 507 refusal holds as before, which meets #123.
Model: opus-5-5
95e0c30ad6tob068d19b73