fix(orchestrator): restore pause state after allocation failure - #100
fix(orchestrator): restore pause state after allocation failure#100morluto wants to merge 2 commits into
Conversation
cfb1114 to
08aaba5
Compare
|
🔍 OpenCodeReview found 3 issue(s) in this PR.
|
fec07fa to
3bfe936
Compare
3bfe936 to
a465e71
Compare
| if let Err(error) = self | ||
| .persister | ||
| .delete_record_and_artifacts(&sandbox_id) | ||
| .await | ||
| { | ||
| warn!(error = ?error, "failed to clean up persisted state for missing sandbox handle"); | ||
| } | ||
| return Err(OrchestratorError::SandboxNotFound(sandbox_id)); |
There was a problem hiding this comment.
[bug · medium]
This discards the persistence deletion failure after the metadata has already been removed, leaving no retry path. A stale paused record is loaded back into the metadata store by load_all on restart, so this can resurrect the sandbox that this branch just removed (and orphan artifacts in the meantime). Make failed deletion durable/retryable via reconciliation, or preserve enough metadata to retry cleanup rather than reporting only SandboxNotFound.
| self.sandboxes.write().await.insert(sandbox_id, handle); | ||
| self.restore_proxy_route(sandbox_id, removed_proxy_route) | ||
| .await; | ||
| let restore_result = self | ||
| .store | ||
| .update_state_if_state( | ||
| &sandbox_id, | ||
| SandboxState::Running, | ||
| &[SandboxState::Pausing], | ||
| ) | ||
| .await; |
There was a problem hiding this comment.
[bug · high]
The runtime and proxy route become active before the fallible metadata rollback. update_state_if_state returns an error on a backend failure or state conflict; in that case this branch returns with a routable runtime while metadata may remain Pausing. Concurrent pause/delete calls can then wait indefinitely for that transition, while data-plane traffic still reaches the sandbox. If publishing Running fails, undo the handle/route restoration and stop or otherwise reconcile the runtime before returning; add a failure-injection test for this path.
| assert_eq!( | ||
| image_refs.unpinned(), | ||
| vec![ | ||
| RuntimeImageOwner::StartingSandbox(sandbox_id), | ||
| RuntimeImageOwner::PausedSandbox(sandbox_id), | ||
| ] | ||
| ); |
There was a problem hiding this comment.
[test · high]
This expectation legitimizes releasing the only durable hold on runtime_artifacts as soon as the sandbox is restored. A maintenance pass can snapshot the running set while the handle is detached, then continue after this unpin; its stale snapshot contains neither this sandbox nor a hold, so GC may delete artifacts still used by the restored runtime. Please change the rollback implementation and this assertion so protection is retained or atomically transferred to a running/runtime owner until maintenance is guaranteed to observe the restored handle, and add a test that interleaves maintenance with this rollback.
What does this PR do?
Restores a running sandbox when paused-artifact-root allocation fails before the backend pause begins.
Previously,
pause_sandbox_innerdetached the runtime handle and proxy route and then propagated an allocation error with?. That skipped the rollback used by later pause failure paths, leaving metadata inPausingwhile the live runtime was no longer routable.The failure path now restores the runtime handle and proxy route, transitions metadata from
Pausingback toRunning, and releases the temporaryPausedSandboximage ownership before returning the allocation error. If the metadata transition also fails, the returned internal error preserves both failures.Closes #99.
How was it tested?
pause_artifact_root_allocation_failure_restores_running_for_retry, which deterministically fails the first artifact-root allocation and verifies:Runningwith no paused state;Paused.cargo test -p agentenv --lib orchestrator::service::tests::pause_artifact_root_allocation_failure_restores_running_for_retry -- --exact --nocapturecargo fmt --all -- --checkgit diff --check main...HEADCompatibility
No API, persistence format, or successful pause behavior changes. This only changes rollback after an artifact-root allocation error that occurs before
SandboxBackend::pauseis called.Suggested review order
src/orchestrator/service.rs.src/orchestrator/tests.rs.