Skip to content

refactor(coderd): number chat debug steps in the database - #31007

Draft
ibetitsmike wants to merge 3 commits into
mike/chatdebug-stream-finalize-oncefrom
mike/chatdebug-db-step-numbers
Draft

ibetitsmike wants to merge 3 commits into
mike/chatdebug-stream-finalize-oncefrom
mike/chatdebug-db-step-numbers

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

InsertChatDebugStep now numbers a step after the run's highest step when the caller passes zero, so chatdebug stops numbering steps in process memory. CreateStepParams loses StepNumber, beginStep no longer calls nextStepNumber or syncStepCounter, and CreateStep replaces 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. CreateStep therefore takes pg_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 new TestService_CreateStep_NumbersConcurrentSteps holds 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_RetriesDuplicateStepNumbers becomes TestService_CreateStep_NumbersStepsPerRun, and TestService_CreateStep_ListRetryErrorWins goes 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 from CreateStep, and an unclassified missing run. One mutant survives and is equivalent: running the insert on s.db instead of tx inside the same InTx callback, 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 of service.go with garbage in it fails to build.

Review focus: @step_number stays as an override. Production passes zero, and the fixtures in querier_test.go, dbauthz_test.go, dbpurge_test.go and exp_chats_test.go keep 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.go and queries.sql.go change 15 more.

Validation:

  • make gen/db changes only querier.go and queries.sql.go.
  • go test -race -count=1 -p 4 -parallel 4 ./coderd/x/chatd/chatdebug/... passes, and go 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/ and go 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.

  1. refactor(coderd): delete the chat debug run and step heartbeats #30988 Delete the chat debug run and step heartbeats
  2. refactor: delete chatdebug FinalizeStale and the stale threshold #30989 Delete FinalizeStale and the stale threshold
  3. refactor: delete the FinalizeStaleChatDebugRows query #30995 Delete the FinalizeStaleChatDebugRows query
  4. test(coderd/x/chatd): pin the debug runs that turns, titles and status labels record #30933 Pin the debug runs that turns, titles and status labels record
  5. refactor(coderd/x/chatd): create and finalize debug runs through one helper #30934 Create and finalize debug runs through one helper
  6. test(coderd/x/chatd/chatdebug): table the stream wrapper tests and cover their status rules #30980 Table the stream wrapper tests and cover their status rules
  7. refactor(coderd/x/chatd/chatdebug): share one finalize-once lifecycle between the stream wrappers #30981 Share one finalize-once lifecycle between the stream wrappers
  8. This PR: Number chat debug steps in the database
  9. refactor(coderd/x/chatd/chatdebug): delete the process-global step counters #31008 Delete the process-global step counters
  10. chore(coderd/database): drop the chat debug stale-sweep indexes #31009 Drop the chat debug stale-sweep indexes
  11. refactor(coderd/x/chatd): drop the unused runnerCtx from the runner debug turn #31010 Drop the unused runnerCtx from the runner debug turn

Xum, an AI agent, opened this PR for @ibetitsmike and wrote this description.

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.
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Xum, an AI agent, requested this review for @ibetitsmike.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-18T20:55:55.168577Z 880696c Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: ff1c2f9dea

ℹ️ 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".

@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Xum, an AI agent, requested this review for @ibetitsmike.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread coderd/database/queries/chatdebug.sql
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.
@ibetitsmike

Copy link
Copy Markdown
Collaborator Author

@codex review

Xum, an AI agent, requested this review for @ibetitsmike.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 👍

Reviewed commit: 880696cefd

ℹ️ 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".

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant