diff --git a/crates/worker-runtime/src/runtime.rs b/crates/worker-runtime/src/runtime.rs
index 62be7430..3ed3f76f 100644
--- a/crates/worker-runtime/src/runtime.rs
+++ b/crates/worker-runtime/src/runtime.rs
@@ -1867,16 +1867,49 @@ impl Runtime {
let _operation_guard = operation_lock
.lock()
.map_err(|_| RuntimeError::StatePoisoned)?;
+ let (backend, execution_handle) = {
+ let state = self.lock()?;
+ state.ensure_running()?;
+ state.ensure_worker_ref(worker_ref)?;
+ let worker = state.worker(worker_ref)?;
+ if worker.status.is_active() {
+ return Err(RuntimeError::InvalidRequest(format!(
+ "worker {} is running and must be stopped before deletion",
+ worker_ref.worker_id
+ )));
+ }
+ (
+ state.execution_backend.clone(),
+ worker.execution_handle.clone(),
+ )
+ };
+ if let Some(handle) = execution_handle {
+ let backend = backend.ok_or_else(|| RuntimeError::ExecutionBackendUnavailable {
+ message: "Worker deletion requires its execution backend to confirm shutdown"
+ .to_string(),
+ })?;
+ let result = backend.stop_worker(&handle);
+ if !result.is_accepted() {
+ return Err(RuntimeError::WorkerExecutionRejected {
+ worker_id: worker_ref.worker_id,
+ operation: result.operation,
+ outcome: result.outcome,
+ message: result.message_or_default(),
+ result,
+ });
+ }
+ }
let mut state = self.lock()?;
state.ensure_running()?;
state.ensure_worker_ref(worker_ref)?;
let worker = state.worker(worker_ref)?;
if worker.status.is_active() {
return Err(RuntimeError::InvalidRequest(format!(
- "worker {} is running and must be stopped before deletion",
+ "worker {} became active before deletion",
worker_ref.worker_id
)));
}
+ state.delete_worker_snapshot(&worker_ref.worker_id)?;
let removed = state.workers.remove(&worker_ref.worker_id).ok_or_else(|| {
RuntimeError::WorkerNotFound {
worker_id: worker_ref.worker_id,
@@ -1892,7 +1925,6 @@ impl Runtime {
.retain(|event| event.worker_ref != *worker_ref);
state.publish_worker_removed(worker_ref.worker_id, removed_workspace_id.as_deref())?;
state.persist_runtime_snapshot()?;
- state.delete_worker_snapshot(&worker_ref.worker_id)?;
Ok(WorkerDeleteResult {
worker_id: removed.worker_id,
deleted: true,
@@ -4136,6 +4168,7 @@ mod tests {
#[derive(Default)]
struct TestExecutionBackend {
dispatch_result: Mutex