Repository navigation
refactor(coderd): number chat debug steps in the database - #31007
ibetitsmike wants to merge 3 commits into
Conversation
InsertChatDebugStep numbers a step after the run's highest step when the caller passes zero, and chatdebug.Service.CreateStep no longer takes a step number. CreateStep keeps its retry on the (run_id, step_number) unique violation but drops the list-and-bump loop, because a retried insert takes a fresh snapshot. beginStep no longer reads the process-global step counters.
|
@codex review
|
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 50e99568c8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
InsertChatDebugStep reads the run's highest step from its statement snapshot, which Postgres takes before the statement waits on the run row. Concurrent creates for one run therefore collided and retried, and with more than 10 of them the last one ran out of attempts and its step was dropped. CreateStep now takes a per-run advisory lock in an earlier statement of the same transaction, so each insert sees every step that was committed before it, and the retry loop is gone.
|
@codex review
|
|
Codex Review: Didn't find any major issues. 👍 Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
InsertChatDebugStepnow numbers a step after the run's highest step when the caller passes zero, so chatdebug stops numbering steps in process memory.CreateStepParamslosesStepNumber,beginStepno longer callsnextStepNumberorsyncStepCounter, andCreateStepreplaces its collision retry, which listed the run's steps and bumped the number, with a per-run lock. #31008 deletes the counters, which no production code reads after this PR.Why it is safe: Postgres takes the insert's snapshot before the statement waits on the run row, so creates that waited on the same run read the same highest step.
CreateSteptherefore takespg_advisory_xact_lock(LockIDChatDebugRunSteps(run))in its own statement and inserts in the same transaction, so each insert starts after the previous holder committed. The newTestService_CreateStep_NumbersConcurrentStepsholds the run row, starts 20 creates, waits until all of them wait on a lock, then commits and checks the numbers 1 to 20. It passes 10 of 10 runs, and fails 10 of 10 with a 10-attempt collision retry in place of the lock.TestService_CreateStep_RetriesDuplicateStepNumbersbecomesTestService_CreateStep_NumbersStepsPerRun, andTestService_CreateStep_ListRetryErrorWinsgoes with the list call it covered. Mutants that fail the chatdebug tests: no lock, the lock outside the transaction, the lock keyed by chat, a constant number, storing the zero, numbering across runs, a nonzero number fromCreateStep, and an unclassified missing run. One mutant survives and is equivalent: running the insert ons.dbinstead oftxinside the sameInTxcallback, because the insert still commits before the transaction releases the lock. Running the insert after the transaction commits fails the new test with a duplicate key. A copy ofservice.gowith garbage in it fails to build.Review focus:
@step_numberstays as an override. Production passes zero, and the fixtures inquerier_test.go,dbauthz_test.go,dbpurge_test.goandexp_chats_test.gokeep their explicit numbers. No test depends on the override (a mutant that ignores it survives), because every fixture numbers its steps in insert order. Dropping the parameter would touch about 20 fixtures outside chatdebug.The PR removes more than it adds: +179/-233 hand-written lines. The generated
querier.goandqueries.sql.gochange 15 more.Validation:
make gen/dbchanges onlyquerier.goandqueries.sql.go.go test -race -count=1 -p 4 -parallel 4 ./coderd/x/chatd/chatdebug/...passes, andgo test -count=10 -run TestService_CreateStep ./coderd/x/chatd/chatdebug/passes all 6 tests 10 of 10 times.go test -count=1 -run ChatDebug ./coderd/database/ ./coderd/database/dbpurge/andgo test -count=1 -run Debug ./coderd/x/chatd/(19 tests) pass, and the 25 chatd debug-run tests pass under-race.golangci-lint run --fix=false ./coderd/x/chatd/chatdebug/... ./coderd/database/reports 0 issues, and the pre-commit hook passed.Stack
This stack deletes the stale debug-run sweep, then simplifies the chatdebug debug-run, stream wrapper and step numbering code, drops the indexes the sweep used, and last deletes a runner debug field that lost its only reader with the heartbeats. The debug-run and stream wrapper refactors each sit on a test-only layer that pins the behavior they keep.
FinalizeStaleand the stale thresholdFinalizeStaleChatDebugRowsqueryrunnerCtxfrom the runner debug turn