fix(sandbox): retry provider updates rejected as modified concurrently - #6523
Conversation
EnsureProvider already retries the "unsupported provider type or profile" error from a concurrent ImportProfile delete+reimport, but not the error that follows it: when several fullsend runs start on one gateway right after a profile changed, each re-imports the profile and then updates the provider, and the gateway rejects all but one update with "provider was modified concurrently (current resource_version: N)". The losing run failed outright before the agent started. This hit the fullsend-ai/agents functional tests on every PR that changes profiles/fullsend-vertex-ai.yaml (eval parallelism 4): one triage case died in ~1s with that error in three of four runs of agents#965, and on main — where the profile is unchanged — never. Treat the conflict as the same transient class and retry the create+update cycle with the existing backoff; the update is idempotent. openshell wraps the message across lines with a box-drawing gutter, so it is matched with a regexp across the wrap rather than as a contiguous substring — the first attempt at a substring match did not match the real output. Assisted-by: Claude (code) Signed-off-by: Wayne Sun <gsun@redhat.com>
|
🤖 Finished Review · ✅ Success · Started 2:35 PM UTC · Completed 2:48 PM UTC Commit: |
PR Summary by QodoRetry EnsureProvider when provider update is rejected due to concurrent modification
AI Description
Diagram
High-Level Assessment
Files changed (2)
|
Code Review by Qodo🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)
Great, no issues found!Qodo reviewed your code and found no material issues that require reviewTip of the day💡 Did you know, you can turn these tips off under Display preferences |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
Looks good to me |
|
Merge-queue E2E failed twice (runs 32889823311, 32894999360), both with |
|
🤖 Finished Retro · ✅ Success · Started 9:17 PM UTC · Completed 9:26 PM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $3.59 |
Retro: PR #6523 —
|
Summary
EnsureProviderretries the transientunsupported provider type or profileerror from a concurrentImportProfiledelete+reimport, but not the error that follows it on a shared gateway: when severalfullsend runs start right after a profile changed, each re-imports the profile and then updates the provider, and the gateway rejects all but one update withprovider was modified concurrently (current resource_version: N). The losing run failed before the agent started. This retries that conflict with the existing backoff (the update is idempotent).Related Issue
No tracker issue. Observed in the fullsend-ai/agents functional tests (eval
parallelism: 4): one triage case died in ~1 s at $0.00 with this error in three of four runs of fullsend-ai/agents#965 (which changesprofiles/fullsend-vertex-ai.yaml), including a merge-queue attempt, and never onmainwhere the profile is unchanged. Any PR touching a shared profile can hit it.Changes
internal/sandbox/sandbox.go:isUnsupportedProviderErr→isTransientProviderErr, which also matches the optimistic-concurrency rejection; the existing retry loop (3 attempts, 500 ms backoff) now covers both. openshell wraps the message across lines with a box-drawing gutter ("provider was modified/│ concurrently (…)), so the match is a regexp across the wrap (provider was modified\W+concurrently) — a contiguous substring does not match the real output (the new test reproduces the wrapped form).internal/sandbox/sandbox_test.go:TestEnsureProvider_RetriesConcurrentUpdateConflict(fakeopenshell: create → "already exists", update → conflict twice, then success; asserts 3 update attempts and overall success) andTestIsTransientProviderErr(wrapped and unwrapped forms, negatives).Testing
make lintequivalent on the changed files:gofmt,go vet, pre-commit — clean (no golangci-lint on this host; CIbuild/testcover it)go test ./internal/sandbox/passesmain) — the triage race should no longer fail the jobChecklist
!for breaking changes)