Repository navigation
fix(server): retry stop lifecycle writes after concurrent updates - #4395
Merged
Merged
Conversation
The stop path wrote Stopping and Stopped with a single compare-and-swap. In HA deployments every replica applies compute driver watch events for the terminating runtime without the per-replica lifecycle gate, so a watch write landing between the re-read and the CAS failed the stop RPC with "update sandbox lifecycle failed due to concurrent modification" and left the sandbox in Stopping. Retry both writes on PersistenceError::Conflict up to STOP_PHASE_CAS_RETRY_LIMIT, re-reading the sandbox on each attempt. The Stopping write re-runs the stop preconditions and the name check; the Stopped write proceeds only while the record is still Stopping, returns an already Stopped record as-is, and aborts on any other phase. Gateway startup recovery of retained Stopping sandboxes now shares the same helper instead of writing against its pre-driver snapshot. Signed-off-by: Piotr Mlocek <pmlocek@nvidia.com>
pimlock
requested review from
a team,
derekwaynecarr,
mrunalp and
sjenning
as code owners
October 10, 2026 00:31
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
pimlock
commented
Oct 10, 2026
pimlock
left a comment
Collaborator
Author
There was a problem hiding this comment.
gator-agent
PR Review Status
This focused server fix retries lifecycle compare-and-swap writes that lose to concurrent HA watch updates. The initial code review found no blocking issues, but the required standard E2E workflow has not yet been dispatched with its new label.
Action required: A maintainer must open Actions run 38009458482 and click Re-run all jobs so test:e2e executes for the current head.
Blocking findings:
- No blocking findings remain
Carried findings:
- None
Non-blocking suggestions:
- None
Gator metadata
- Validation: Project-valid focused HA sandbox lifecycle race fix from a repository maintainer
- Docs: Not needed because this changes internal retry behavior without changing the user-facing contract
- Checks: Branch Checks, Helm Lint, Trivy Changes, DCO, and vouch gates are green; required standard E2E awaits dispatch
- E2E:
test:e2eandtest:e2e-kubernetesare applied; the label helper requires Re-run all jobs on run 38009458482 - Head SHA:
0667f74e12f89d5f60de66f32c68c7a33ea649dc - Base SHA:
0ccc6b9a053fdaf47700e91c1b8ed858f2afed4f - Merge base SHA:
d789ec613b829044e4580f6cda7f5d4648a31285 - Patch ID:
28e3fe2fdaea4f7513129e6a006b02c58eed561c - Gator payload:
11 - Review mode:
initial - Previous reviewed SHA: none
- Review budget exhausted: no
- Maintainer decision required: no
- Next state:
gator:blocked - Blocked reason:
test_dispatch_required
johntmyers
approved these changes
Oct 12, 2026
9 of 10 tasks
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
openshell sandbox stopwritesStoppingand thenStoppedwith one compare-and-swap each.In HA, every gateway replica applies watch events for the terminating pod, and the per-replica lifecycle lock doesn't cover them.
If one of those writes lands between the re-read and the CAS, stop fails with
Aborted: update sandbox lifecycle failed due to concurrent modificationand the sandbox stays inStopping. This PR retries both writes on conflict, the same way start already does.Seen in Branch E2E Checks run 38004123998 ("Kubernetes HA E2E (Rust smoke)", scenario
sandbox-lifecycle/stop-start/stop).Related Issue
No issue required. Small bug fix for an HA race seen in CI.
Changes
stop_sandboxretries theStoppingwrite. Each retry re-reads the sandbox, checks the name, and re-runs the phase checks.commit_sandbox_stoppedretries theStoppedwrite while the sandbox is stillStopping. It returns early if the sandbox is alreadyStoppedand aborts on any other phase.Stoppinguses the same helper. It used to write against a copy read before the driver call, so any watch event during the stop made it fail.Delete already retries its phase write. The automatic-restart claim backs off on conflict by design, so I left it alone.
Testing
mise run pre-commitpassesThe new test
stop_retries_lifecycle_writes_after_concurrent_replica_writeuses a SQLite trigger to add a conflicting write before each CAS. Stop still ends inStopped. With retries disabled the test fails with the CI error. I didn't re-run the Kubernetes HA E2E job locally.Checklist