refactor(storage): claim applies only through the operation ladder - #934
Conversation
FindNextApply is gone: drivers claim work through the operation ladder (FindNextApplyOperation and friends), and a specific apply is claimed with ClaimApplyByID, which shares the same six-arm claim predicate and lease rotation. The predicate's coverage — pending-with-child-rows, stale-heartbeat reclaim, retryable budget, and start control requests — now lives entirely in the ClaimApplyByID tests, and the tern operator integration helpers claim each dispatched apply by ID the way api.Service drivers do. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
32dbeb8 to
33439fa
Compare
There was a problem hiding this comment.
Pull request overview
This PR refactors the storage-layer apply claiming flow to eliminate the now-dead queue-scan claim path and ensure all drivers acquire apply leases exclusively through the operation-claim ladder plus a single by-ID claim predicate (ClaimApplyByID). This reduces the risk of safety-critical predicate drift by consolidating claimability rules and lease rotation into one exercised path.
Changes:
- Removed the apply queue-scan claim API (
ApplyStore.FindNextApply) and updated callers to claim applies by ID viaClaimApplyByID. - Updated operator-like tern integration helpers to resolve dispatched applies from storage and claim them by ID, matching the production driver pattern.
- Moved/trimmed tests to pin the unified claim predicate via
ClaimApplyByIDand updated integration tests to drive specific queued applies by identifier.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/tern/local_taskless_completion_integration_test.go | Switches taskless-apply tests from queue-scan claiming to ClaimApplyByID. |
| pkg/tern/local_resume_scope_integration_test.go | Updates resume-scope test to claim the specific apply by ID and adjusts explanatory comment. |
| pkg/tern/local_dispatch_shard_integration_test.go | Starts the test operator with a specific apply identifier so it can claim by ID. |
| pkg/tern/local_control_volume_integration_test.go | Replaces “drive next queued apply” helper usage with “drive this queued apply” by identifier. |
| pkg/tern/local_control_taskless_integration_test.go | Updates taskless control-flow tests to drive/claim the specific apply via ClaimApplyByID. |
| pkg/tern/local_control_reconcile_integration_test.go | Updates reconcile-flow tests to synchronously drive the specific queued apply by identifier. |
| pkg/tern/local_control_completed_engine_integration_test.go | Updates completed-engine control test to drive/claim the specific apply via ClaimApplyByID. |
| pkg/tern/local_client_integration_test.go | Adds helpers to resolve dispatched applies and updates operator/drive helpers to claim by ID rather than scanning. |
| pkg/storage/storage.go | Removes FindNextApply from ApplyStore and updates interface docs to reflect ClaimApplyByID. |
| pkg/storage/README.md | Updates recovery documentation to reference ClaimApplyByID instead of FindNextApply. |
| pkg/storage/mysqlstore/claimable_states_test.go | Updates comments describing the pending-claim arm now pinned via ClaimApplyByID. |
| pkg/storage/mysqlstore/apply_operations.go | Updates comments tying operation-claim behavior to the consolidated apply-claim predicate. |
| pkg/storage/mysqlstore/apply_operations_test.go | Updates parity/coverage comments to reference ClaimApplyByID and renamed apply-level concurrency test. |
| pkg/storage/mysqlstore/applies.go | Removes the queue-scan claim implementation and retains a single ClaimApplyByID implementation for apply leases. |
| pkg/storage/mysqlstore/applies_test.go | Ports/removes queue-scan claim tests and re-anchors predicate coverage on ClaimApplyByID. |
| pkg/api/config.go | Updates operator driver config documentation to no longer reference FindNextApply directly. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…the by-ID claim The by-ID claim is the parent-lease gate every drive acquires, so its own predicate arms deserve direct pins: a stopped apply whose start request failed must stay stopped until an operator re-requests the start, and an apply parked at the cutover gate must be reclaimable once its driver's heartbeat goes stale while staying owned while fresh. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
🤖 Review findings - created by Kiran's code review agent - for pull/934, c4e6889. Verdict: 6 findings — none blocking: 3 non-blocking (the recovery README now mis-describes how stale work is discovered, stale claim-concept comments including two in files this PR touches, two small coverage narrowings), 3 suggestions (#916 heads-up, a decorative control request in a new test, the remaining ladder mirror as the next dedup target). The core of the PR — the textual merge of Non-blocking
General suggestions
The one thing that could have broken, verifiedThe diff textually splices two functions into one: it deletes Verified correct
This review was generated by Claude Code (claude-fable-5). |
…t lease The recovery README now separates discovery (the operation ladder scans for claimable work) from leasing (ClaimApplyByID leases the parent the caller already identified), and names all four claim-predicate families. Comments that still described a whole-apply queue claim now name the by-ID claim or the stop-reconciliation drive that actually runs. Test coverage restored where ports had narrowed it: the setup-phase claim test exercises all five PlanetScale setup states, and the failed- start re-request test ends by proving a repeat claim cannot steal the fresh lease after the stopped-to-resuming transition. The stale-cutover test drops a decorative control request — the claim comes from the stale-active arm, and the doc comment now says so. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
🤖 Thanks for the thorough pass — the byte-identical splice verification and the parity cross-check are exactly the assurances this PR needed. Addressed in ac9fcaa (new commit, post-approval):
This reply was drafted by Claude Code (claude-fable-5) on Armand's behalf. |
Why this matters
The storage layer had two byte-identical six-arm claim predicates: the queue-scan claim and the by-ID claim. Two copies of a safety-critical predicate drift — an arm added to one and not the other silently changes which applies a driver can recover. With drivers claiming queued work exclusively through the operation ladder, the queue-scan copy has no production caller left.
What it does
ApplyStore.FindNextApply(interface + mysqlstore). Drivers claim queued work through the operation ladder (FindNextApplyOperationand friends) and claim one specific apply withClaimApplyByID, which carries the same claim predicate — pending with child rows, stale-heartbeat reclaim, retryable within budget, pending start control requests — and the same lease rotation.ClaimApplyByID: six tests ported in place, two re-pinned directly on the by-ID claim (a failed start request keeps a stopped apply stopped until re-requested; a stalewaiting_for_cutoverapply is reclaimable while a fresh one stays owned), and five removed where a live equivalent already pins the same predicate arm.api.Servicedrivers do.Northstar: one claim predicate, one lease rotation path, exercised by every driver and every test.
Follows #933, which removed the apply-level claim mode this loader served.
🤖 Generated with Claude Code