3.6 KiB
3.6 KiB
v1.1 task 01: review fixes — cancelled clients are recorded; empty usage is []
Branch: v1.1 (create it from master: git switch master && git switch -c v1.1; git status --short must be empty first, otherwise stop)
Commit subject: Review fixes: record cancelled requests as 499; empty usage is an array
What the reviewer observed
- A client that disconnects mid-stream leaves no accounting row: after
curl -m 0.4 -N …against a streaming completion,/_crossbar/usagestayed empty. Task 05's rule 5 said the reverse proxy'sErrorHandlerdoes nothing oncontext.Canceled; rule 6 said "record what you have whenServeHTTPreturns". The second rule was not applied on that path, and the same gap exists for a client that gives up while waiting in the limiter queue (rule 4 said "just return, log 499"). Cancelled requests held a slot and cost prefill; usage and error rate must see them. The task text was ambiguous (owner's fault); the fix is still needed. GET /_crossbar/usagewith no rows answersnull. The spec said a JSON array. Clients iterate the result;nullis not iterable.
Files
- Copy (never edit afterwards):
internal/proxy/cancel_test.go,internal/admin/usage_empty_test.go - Modify: files under
internal/proxy/as needed (forward.go,proxy.go),internal/admin/admin_ops.go(or wherever the usage handler lives),docs/implementer-log.md
Rules
- Every request that reached step 3 of
ServeHTTP(a lease was acquired) writes exactly onestore.Requestrow, on every exit path: normal completion, upstream error (502), queue full (503), client cancelled while queued (499,Err: "client cancelled while queued"), client cancelled during the forward (499,Err: "client cancelled", with whatever tokens the tee had seen). Detect the forward case withr.Context().Err() != nilafterrp.ServeHTTPreturns, or in theErrorHandlerwhenerrors.Is(err, context.Canceled); do not write to the client in that case, do not mark the host down, but do record. Status 499 is not an HTTP status the client sees; it is the row's status (and the log line's), as nginx does. /_crossbar/usageJSON encodes an empty result as[]: initialise the slice (rows := []store.UsageRow{}/make(..., 0)) before encoding, on everybyvalue and with or withoutsince. The text form prints its header line even with no rows.- Nothing else changes. Existing tests must keep passing; the two new ones must pass.
Steps
- 1. Branch and copy.
git switch master && git switch -c v1.1
cp docs/plans/v1.1/_files/internal/proxy/cancel_test.go internal/proxy/
cp docs/plans/v1.1/_files/internal/admin/usage_empty_test.go internal/admin/
- 2. See them fail.
go test -run 'Cancel|UsageEmpty' ./internal/proxy/ ./internal/admin/. Expected: all three tests fail (no 499 row,body "null"). If one passes already, stop and report. - 3. Fix.
gofmt -w internal/. - 4. See everything pass.
go test -race -count=2 ./.... The cancel tests are timing-based with generous margins. - 5. Run the gate.
make gate. Expected last line:gate: ok. - 6. Log and commit. Row
v1.1/01-review-fixes.
git add internal/proxy internal/admin docs/implementer-log.md
git commit
Done when
- Step 2 failed before the fix and
go test -race -count=2 ./...passes after;make gateprintsgate: ok; both copied tests byte-identical to_files/.
Stop and report if
- Step 2 passes before any change, or the cancel tests fail intermittently after the fix (report the failure text).