GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||
GeezerVison is showing github.com — fix(coderd/database): lock the workspace row when claiming a prebuild by kevinh-canva · Pull Request #31468 · coder/coder Conversation
Contributor
Context
When several users claim from the same preset at once, two claims can select the same prebuild. The second claim waits on the first claim's row lock in the outer We hit this in load testing for a training session with hundreds of users claiming at once. More than half of the claims returned 409, even with client-side retries. IntentLock the underlying Also filter on This changes only the query text. There is no schema or migration change, and Testing
Before the fix (test only): After the fix: Also run against Postgres, on both
NotesThe same patch applies cleanly to Note This PR was written with help from an AI coding agent (Claude). I reviewed the change and the verification output above.
Sorry, something went wrong. Uh oh!
There was an error while loading. Please reload this page. All reactions
ClaimPrebuiltWorkspace locked the workspace_prebuilds view with FOR UPDATE OF p SKIP LOCKED. The view is built from CTEs, and Postgres does not push row locks into a CTE, so the clause locked nothing. Concurrent claims could pick the same prebuild. The second claim waited on the first claim's row lock, then reassigned the workspace to its own user. The first user's next build then failed with a 409. Join and lock the underlying workspaces row instead. Also check its owner_id, because Postgres rechecks conditions on a locked row. That excludes a prebuild that a concurrent transaction has just claimed. Co-authored-by: Forge <[email protected]>
|
There was an error while loading. Please reload this page.
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. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
… deleted rows FOR UPDATE is stronger than the FOR NO KEY UPDATE lock the outer UPDATE takes. It also blocks FK KEY SHARE checks from inserts that reference the workspace, so a reconciler delete build racing a claim can deadlock with the claim's own build insert. FOR NO KEY UPDATE still conflicts between claims, so SKIP LOCKED behaves the same. Also exclude soft-deleted rows on the locked workspace so the row recheck rejects a prebuild deleted while the claim is in flight, and add a test that a claim racing an open claim gets a different prebuild without blocking. Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
Hey @kevinh-canva, thanks for putting this together. I pushed to this branch with some changes, please don't force push and overwrite them. My commit switches the lock to |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
#31518) `ClaimPrebuiltWorkspace` locked the `workspace_prebuilds` view with `FOR UPDATE ... SKIP LOCKED`, but the view is built from CTEs, so nothing got locked. Concurrent claims picked the same prebuild and the losers got a 409 (a customer saw 28 of 30 fail). This locks the `workspaces` row directly (`FOR NO KEY UPDATE SKIP LOCKED`), rechecks owner and deleted on it, and checks eligibility with per-workspace index lookups instead of the views. It uses `=` instead of `IN` so one claim can't take two prebuilds, filters on the preset's template so other templates' prebuilds aren't scanned, and claims oldest first so prebuilds are used before they hit the preset TTL. Query-only, no migration, applies cleanly to release/2.38. Builds on #31468 by Kevin Ha (Canva). Benchmarks (Postgres 17, 20k users, 320k builds, 600 ready prebuilds): ~12 ms per claim (was ~640 ms), and 500 concurrent claims got distinct prebuilds in ~1.5 s. Known limitations: - Each claim still checks every prebuild of the preset's template (other presets included) before sorting. That's a few ms at hundreds of prebuilds per template. - Pre-existing: a reconciler delete during a claim can still 409. Follow-up is a `deleting_at` marker the claim skips. --------- Co-authored-by: Kevin Ha <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]>
|
Closing this PR, we merged a different one to address this issue |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.