compose: avoid panics in cleanup and block feed

This commit is contained in:
andrussal 2025-12-18 23:01:24 +01:00
parent 7dea766801
commit 07ee5bcd20
4 changed files with 31 additions and 14 deletions

View File

@ -118,7 +118,7 @@ impl DeploymentOrchestrator {
let (block_feed, block_feed_guard) = client_builder
.start_block_feed(&node_clients, &mut environment)
.await?;
let cleanup_guard = make_cleanup_guard(environment.into_cleanup(), block_feed_guard);
let cleanup_guard = make_cleanup_guard(environment.into_cleanup()?, block_feed_guard);
let context = RunContext::new(
descriptors,

View File

@ -55,6 +55,8 @@ pub enum ComposeRunnerError {
#[source]
source: anyhow::Error,
},
#[error("internal invariant violated: {message}")]
InternalInvariant { message: &'static str },
}
#[derive(Debug, thiserror::Error)]

View File

@ -84,28 +84,38 @@ impl StackEnvironment {
}
/// Convert into a cleanup guard while keeping the environment borrowed.
pub fn take_cleanup(&mut self) -> RunnerCleanup {
RunnerCleanup::new(
pub fn take_cleanup(&mut self) -> Result<RunnerCleanup, ComposeRunnerError> {
let workspace = self
.workspace
.take()
.ok_or(ComposeRunnerError::InternalInvariant {
message: "workspace must be available while cleaning up",
})?;
Ok(RunnerCleanup::new(
self.compose_path.clone(),
self.project_name.clone(),
self.root.clone(),
self.workspace
.take()
.expect("workspace must be available while cleaning up"),
workspace,
self.cfgsync_handle.take(),
)
))
}
/// Convert into a cleanup guard, consuming the environment.
pub fn into_cleanup(self) -> RunnerCleanup {
RunnerCleanup::new(
pub fn into_cleanup(self) -> Result<RunnerCleanup, ComposeRunnerError> {
let workspace = self
.workspace
.ok_or(ComposeRunnerError::InternalInvariant {
message: "workspace must be available while cleaning up",
})?;
Ok(RunnerCleanup::new(
self.compose_path,
self.project_name,
self.root,
self.workspace
.expect("workspace must be available while cleaning up"),
workspace,
self.cfgsync_handle,
)
))
}
/// Dump compose logs and trigger cleanup after a failure.
@ -115,7 +125,10 @@ impl StackEnvironment {
"compose stack failure; dumping docker logs"
);
dump_compose_logs(self.compose_path(), self.project_name(), self.root()).await;
Box::new(self.take_cleanup()).cleanup();
match self.take_cleanup() {
Ok(cleanup) => Box::new(cleanup).cleanup(),
Err(err) => error!(error = %err, "failed to acquire cleanup guard"),
}
}
}

View File

@ -49,5 +49,7 @@ pub async fn spawn_block_feed_with_retry(
}
}
Err(last_err.expect("block feed retry should capture an error"))
Err(last_err.unwrap_or(ComposeRunnerError::InternalInvariant {
message: "block feed retry exhausted without capturing an error",
}))
}