fix(readview): keep status row present during Reset so concurrent Start cannot race
The bug
Reset ran the resetHandler under a FOR UPDATE NOWAIT lock, then DELETEd the readview_status row and committed (releasing the lock) before calling initiateBackFill. Between commit and the first INSERT inside doBackFill, the status row was missing.
A concurrent Start on another instance reaching its messageHandler / startFn in that window saw sql.ErrNoRows from the SELECT, defaulted currentSeqNo to 0, treated backFillInProgress(nil, nil) as false, and entered the currentSeqNo == 0 branch — which calls the same resetHandler again. Two resetHandlers could then race against the same read model.
The fix
Instead of DELETE + later re-INSERT, atomically reset the row in place to (current_seq_no=0, filler=hostname, started=now). The row never disappears; from this point onward other instances see backFillInProgress=true and back off until our doBackFill clears the filler. The lock window doesn't extend across the rebuild — it doesn't need to — but the state visible to other instances during the window is now "a backfill is in progress" rather than "nothing exists".
Test plan
- Updated
TestReadview_Resetsubtests (update_status_error / commit_error / max_global_seq_error / events_error / success) to expect the new INSERT-on-conflict statement instead of DELETE - Shifted the doBackFill final-commit timestamps in two subtests by one
r.now()tick to account for the fresh INSERT consuming one now-call - Full suite (
go test -race ./...) green