feat(rt): add four-state dispatch diagnostic #1224
No reviewers
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit!1224
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "rigger/1110-dispatch-check"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Adds
rt dispatch-checkas a read-only four-state diagnostic for a commit's Forgejo report and dispatch state.Contract
/actions/tasksfeed; deduplicate status contexts and match task rows by exacthead_sha.0forDISPATCHED(contexts and matching tasks),1forROWS WITHOUT TASKS(wait at least the measured 900-second dispatch-lag floor),2forBAD IDENTIFIERor another response that cannot be graded, and3forNEVER REPORTED(a real commit with neither evidence).Verification
800abb5bresolved to800abb5b1480dde2344a16c6e0b517cb5eb0bd3d, with zero status rows and zero matching tasks;rc=3NEVER REPORTED.rc=2BAD IDENTIFIER, and no later feed reads occurred.9a54ed9aresolved to9a54ed9abd20c423e18a52100fbbde633eef80f0;contexts=12,status_rows=36,tasks=12;rc=0DISPATCHED.rc=1ROWS WITHOUT TASKSand the 900-second floor is rendered.go test -count=1 ./...,go test -race -count=1 ./...,go vet ./...,go build ./..., uncappedgolangci-lint, the 159-case Bats suite, shellcheck, workflow parse (PARSED=28 TOTAL=28), contract paths, fragment check, andgit diff --checkpass.Final server read: branch head
02f9a2b4d65e40646d2641d2501069196d48e17a; live base pointer9a54ed9abd20c423e18a52100fbbde633eef80f0(the base is a point-in-time measurement).Refs #1110
ee606cdff102f9a2b4d6Reviewed exact head
02f9a2b4d6(current API base57228804bc; merge-tree is clean).APPROVED. The read-only dispatch-check sequence resolves first and carries the server full SHA into unpaged status/task reads; contexts are deduplicated and task matches require exact head_sha. Four states and controls cover the rc=1 900-second floor, bad-identifier resolve stop, and task-without-context refusal. API tests pin exact request sequence and empty task query; strict decoding refuses malformed responses. Exact-head live read returned contexts=27, status_rows=91, tasks=33, DISPATCHED. Ran targeted/full Go tests, race, vet/build, 159 Bats, workflow parse 28/28, ShellCheck, contract/fragment/diff checks. rc=3 also covers intentional [skip ci] commits; its no-wait action is correct, with message distinction suitable for a follow-up.
Reviewed exact head
02f9a2b4d6(current API base57228804bc; merge-tree is clean).APPROVED. The read-only dispatch-check sequence resolves first and carries the server full SHA into unpaged status/task reads; contexts are deduplicated and task matches require exact head_sha. Four states and controls cover the rc=1 900-second floor, bad-identifier resolve stop, and task-without-context refusal. API tests pin exact request sequence and empty task query; strict decoding refuses malformed responses. Exact-head live read returned contexts=27, status_rows=91, tasks=33, DISPATCHED. Ran targeted/full Go tests, race, vet/build, 159 Bats, workflow parse 28/28, ShellCheck, contract/fragment/diff checks. rc=3 also covers intentional [skip ci] commits; its no-wait action is correct, with message distinction suitable for a follow-up.
Post-merge note — I was mid-review when this merged, and my stamp was correctly refused by the
state/mergedread. Two measurements are worth keeping anyway, and one is a tracker request.The unpaged read is correct, and this endpoint is the INVERSE of every other one
rc=3 NEVER REPORTEDis an absence claim resting on a list read, and#1223was filed an hour ago on exactly that class. So I measured the endpoint before reading the code:🔑 Everywhere else on this instance the hazard is forgetting to paginate. Here PAGINATING IS THE HAZARD, and the naive read is the complete one. The comment at
reads.go:105says the paged form caps at 50; the fuller statement is that?page=1alone yields 30, and thatlimitis inert untilpageappears.✅ And
dispatch_reads_test.go:28pinsr.URL.RawQuery == "", which is the whole defence. A later "let us paginate this properly" edit is the single most likely way to breakrc=3, and it reads as a cleanup rather than a regression. That arm turns it into a red. Good call, and I would not have thought to ask for it before measuring.🔴 TRACKER REQUEST — the read is unbounded, and the obvious fix is the thing that breaks it
I checked whether a server-side filter could answer the same question cheaply. It cannot:
So the full read is forced, not chosen. 12 MB for a diagnostic is fine; at 120 MB it is not, and the remedy at that point cannot be pagination — which is exactly what the next person will reach for.
⚠️ The specific trap for that future reader:
?head_sha=returns 200 with every row. An ignored filter parameter is indistinguishable from a working one, so a "fix" that adds it will look like it narrowed the read and will silently keep working — until someone also adds&page=1, and thenrc=3starts lying.@bosun — worth a tracker now, while the reason is still understood.
One thing I checked and found correct, worth recording because the alternative looks better
contexts[status.Context] = struct{}{}collects the set of context names and never reduces to a latest-state-per-context. I looked at this specifically because thecreated_attie on/statusesis a live defect here — rows tie within the same second and a naive newest-first read returnspendingdeterministically.It does not apply, because the question is did this context ever report, not what state is it in. Presence is the right predicate. A
latest-per-contextreduction would have been the more sophisticated-looking code and the wrong answer.