From cc4c551aaaa9fef514f911972fe2ccdb16ae386c Mon Sep 17 00:00:00 2001 From: xfy Date: Mon, 13 Jul 2026 17:56:42 +0800 Subject: [PATCH] =?UTF-8?q?fix(code-runner):=20=E5=AE=B9=E5=99=A8=E6=B8=85?= =?UTF-8?q?=E7=90=86=E5=A4=B1=E8=B4=A5=E9=87=8D=E8=AF=95+=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E5=91=8A=E8=AD=A6=EF=BC=8C=E9=81=BF=E5=85=8D=E9=9D=99?= =?UTF-8?q?=E9=BB=98=E6=B3=84=E6=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ContainerGuard::drop 之前用 let _ = 吞掉 remove_container 的错误, Docker daemon 瞬时不可用会让容器泄漏且无人知晓。 改为最多重试 3 次(指数退避 200/400/800ms),仍失败则记录 error 级日志 (带 container_id 便于 docker rm -f 兜底)。容器清理是 fire-and-forget, 无法把错误回传业务层,所以用日志暴露故障而非 panic。 --- src/infra/docker.rs | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/infra/docker.rs b/src/infra/docker.rs index f676fba..12dec51 100644 --- a/src/infra/docker.rs +++ b/src/infra/docker.rs @@ -61,12 +61,42 @@ impl Drop for ContainerGuard { fn drop(&mut self) { let docker = self.docker.clone(); let container_id = self.container_id.clone(); + // 容器清理是 fire-and-forget:调用方已返回,无法把错误回传给业务层。 + // 因此重试几次以抵抗瞬时故障(daemon 繁忙 / socket 抖动), + // 仍失败则记录 error 级日志并带上 container_id,便于运维手动 `docker rm -f` 清理, + // 避免容器静默泄漏、长期堆积。 tokio::spawn(async move { - let remove_options = Some(RemoveContainerOptions { - force: true, - ..Default::default() - }); - let _ = docker.remove_container(&container_id, remove_options).await; + let max_attempts = 3u8; + let mut backoff = Duration::from_millis(200); + for attempt in 1..=max_attempts { + let remove_options = Some(RemoveContainerOptions { + force: true, + ..Default::default() + }); + match docker.remove_container(&container_id, remove_options).await { + Ok(()) => return, + Err(e) if attempt < max_attempts => { + tracing::warn!( + attempt, + max_attempts, + "remove_container 失败,稍后重试: {:?}", + e + ); + tokio::time::sleep(backoff).await; + backoff *= 2; + } + Err(e) => { + tracing::error!( + container_id = %container_id, + "重试 {} 次后仍无法删除容器,可能泄漏;请手动执行 `docker rm -f {}`: {:?}", + max_attempts, + container_id, + e + ); + return; + } + } + } }); } }