Skip to content

fix(ctf): launch participant ranges outside the assignment transaction - #2523

Merged
Brad-Edwards merged 3 commits into
devfrom
fix/ctf-provision-outside-claim-transaction
Oct 6, 2026
Merged

Brad-Edwards merged 3 commits into
devfrom
fix/ctf-provision-outside-claim-transaction

Conversation

@Brad-Edwards

Copy link
Copy Markdown
Owner

Summary

provision_participant_range held the participant row lock (transaction.atomic() + select_for_update()) across the entire cms_create_range launch. When a pack declares a feature artifact (#2479), the launch plan calls await_ready. By design, await_ready refuses to run inside a transaction, because the acquisition launcher cannot see an uncommitted claim. As a result, every CTF participant range for such a pack was rejected:

shifter-provisioner.dispatch-failed @ plan: await_ready must not run inside a database transaction

Mission Control launches, spares and recovery do not hit this: they already launch outside a transaction.

Change

  • _claim_for_provisioning holds the row lock only for the already-assigned guard, the PLAT-201 capacity draw and the claim write (range_status="provisioning"), then commits. The existing ctf: scheduler spin-up heartbeat + single-runner election on multi-node portal #942 guard already treats that status as claimed, so concurrent manual and scheduled provisioning still cannot double-assign.
  • The CMS launch runs outside any transaction, and the instance id is recorded afterwards with a conditional update.
  • A failed launch releases the draw and restores the prior range_status, so the retry wrapper can claim again.

Verification

  • tests/ctf/test_services/test_range.py: a new test asserts the launch runs at savepoint depth 0 with the claim already visible. The CMS-failure test now asserts the claim is released.
  • test_range.py, test_capacity_draw_wiring.py, and the provision-filtered API/spares tests pass.
  • Found during live QA of a pack that declares the claude-code feature on a GCP tenant; live re-validation follows.

Refs #2479

provision_participant_range held the participant row lock in one
transaction around the whole CMS launch. A pack that declares a feature
artifact makes the launch wait for the acquisition launcher, which refuses
to run inside a transaction because the launcher cannot see an uncommitted
claim. Every CTF participant range for such a pack was rejected at plan time.

Commit the #942 claim (range_status="provisioning") and capacity draw under
the lock first, launch outside any transaction, then record the instance id.
A failed launch returns the draw and restores the prior status so a retry can
claim again, matching how spares and recovery already launch. Refs #2479.
@Brad-Edwards

Copy link
Copy Markdown
Owner Author

Hold: validating live on a GCP tenant before merge.

…ock baseline

Return the registered user from the claim so the launch keeps its non-null
type, and assert the outside-transaction launch in the existing success test
instead of adding new first-party patch targets (ADR-019-R1).
@Brad-Edwards
Brad-Edwards merged commit ec10c31 into dev Oct 6, 2026
70 checks passed
@Brad-Edwards
Brad-Edwards deleted the fix/ctf-provision-outside-claim-transaction branch October 6, 2026 06:47
@sonarqubecloud

sonarqubecloud Bot commented Oct 6, 2026

Copy link
Copy Markdown

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