Let dev builds shorten the connector's handoff grace, and test requests from before a restart
PR 5 of a stack of 8 that tests basecamp connect end to end. Stacked on #823 (the e2e harness), which is stacked on #822 (the fake Basecamp). It changes no behaviour of a release build.
Why
The connector hands off a request only if it was made at most HandoffGrace (one minute) before the run started. A request older than that is closed as before_this_run: nobody was there to take it, and it is not run late.
That matters most after a crash between admission and handoff. The connector admits a request, dies before it writes the request line, and starts again. Within the grace, the request is handed off (PR 3 tests that, with the default grace). After the grace, it must be closed and never written. Nothing tested that second half end to end, because a test would have to wait out a minute.
What
HandoffOptions.Grace(internal/connector/handoff.go). Zero meansHandoffGrace, so every caller that does not set it keeps the minute. The handoff reads it through a smallgrace()method, as it reads its logger.- A dev-only knob.
connect_handoff_grace_dev.go(//go:build dev) readsBASECAMP_CONNECT_HANDOFF_GRACEas a Go duration.connect_handoff_grace_stub.go(//go:build !dev) reads no environment at all and returns zero, so a release build (goreleaser builds without-tags dev) cannot be affected. This is the same pattern asdev_tag.go/dev_tag_stub.go. There is no hidden flag. runConnectreads it before it touches the account. A value that is not a positive duration is a usage error. A run with the override logsconnector: the handoff grace is overridden for this dev buildon stderr, with the grace and the default.- Log order. The handoff logged
a request from before this run started is not handed offbefore the ledger write. A run stopped between the two left the record admitted while its log said it was closed. The e2e test found this. The log now comes after the write.
Tests
e2e/connect/grace_test.go(a new file; no harness changes). With a 2s grace:connect --hold, a trusted mention, wait for itsadmittedevent line,kill -9,basecamp connect release -P agent, then a restart. On the restart there is no request line, the connector logs the close for that event id, andconnect status --jsonshows no admitted or queued record.- No sleeping. The fake (
WithClock) stamps the request 10s in the past instead of the test waiting out the grace. To the connector it is the same request: the handoff judges only the event'screated_at, as the feed served it, against when the run started, and nothing else in intake or admission readscreated_at. Before the restart, the test checks from the pointer line'screated_atthat the request is already older than the grace. - It needs the knob. 10s is well inside the default minute, so without the shortened grace the request would be handed off and the test would fail.
- Without
-tags devthe test skips and says why: a release build reads no environment for the grace.make test,bin/ci, the unit test job, the race shards and the release workflow all rungo test -tags dev, so it always runs there.
- No sleeping. The fake (
handoff_test.go: a grace of 30s hands off a request made 30s before the run (the boundary included), a grace of 29s closes it asbefore_this_run, and no grace meansHandoffGrace.connect_handoff_grace_dev_test.go(dev-tagged): the parse accepts Go durations and empty (zero), refuses2,soon,0sand-1swith the variable's name in the error, and reads the environment.
go test -tags dev -race -count=10 passes on the new tests. bin/ci is green.
Summary by cubic
Lets dev builds shorten the connector's handoff grace so an end-to-end test can reach a crash-after-grace restart in seconds; release builds read no environment for the grace and keep the one-minute default.
- Adds
HandoffOptions.Grace; zero means the existingHandoffGrace, and only a dev build sets it fromBASECAMP_CONNECT_HANDOFF_GRACE, with invalid values a usage error. - Moves the
before_this_runlog after the ledger write, so a stopped run no longer logs a close it has not yet written. - Adds unit tests for the boundary and default and an e2e test that holds and kills a run, then restarts past a 2s grace; the fake backdates the request instead of the test sleeping.