fix(runner): propagate duration_ms through SSE done event
The SSE streaming path hardcoded '耗时: -' because duration_ms was never threaded through: - docker.rs: OutputChunk::Done now carries duration_ms, computed from start_container to wait completion via Instant::elapsed - sse.rs: DonePayload gains duration_ms, serialized into the done event - runner.rs: WASM done callback formats the real duration instead of '-' The polling fallback path already had correct duration via ExecResult; only the SSE path was missing it.
This commit is contained in:
parent
aa2d7f3f2d
commit
e50941ef24
@ -31,6 +31,7 @@ struct DonePayload {
|
||||
exit_code: Option<i64>,
|
||||
oom_killed: bool,
|
||||
timed_out: bool,
|
||||
duration_ms: u64,
|
||||
}
|
||||
|
||||
/// SSE handler:从 EXEC_STREAMS 取出 receiver(取出即移除,防重复连接),
|
||||
@ -52,12 +53,14 @@ pub async fn exec_stream(
|
||||
exit_code,
|
||||
oom_killed,
|
||||
timed_out,
|
||||
duration_ms,
|
||||
} => Event::default()
|
||||
.event("done")
|
||||
.json_data(DonePayload {
|
||||
exit_code,
|
||||
oom_killed,
|
||||
timed_out,
|
||||
duration_ms,
|
||||
})
|
||||
.unwrap_or_else(|_| Event::default().event("done").data("{}")),
|
||||
})
|
||||
|
||||
@ -569,6 +569,7 @@ mod sse_consumer {
|
||||
exit_code: Option<i64>,
|
||||
oom_killed: bool,
|
||||
timed_out: bool,
|
||||
duration_ms: u64,
|
||||
}
|
||||
|
||||
/// 启动 EventSource 消费 SSE 流。
|
||||
@ -630,17 +631,31 @@ mod sse_consumer {
|
||||
exit_code: None,
|
||||
oom_killed: false,
|
||||
timed_out: false,
|
||||
duration_ms: 0,
|
||||
});
|
||||
|
||||
let (info, err) = if payload.timed_out {
|
||||
("耗时: - · 状态: 超时".to_string(), "超时".to_string())
|
||||
(
|
||||
format!("耗时: {}ms · 状态: 超时", payload.duration_ms),
|
||||
"超时".to_string(),
|
||||
)
|
||||
} else if payload.oom_killed {
|
||||
("耗时: - · 状态: 内存超限".to_string(), "内存超限".to_string())
|
||||
(
|
||||
format!("耗时: {}ms · 状态: 内存超限", payload.duration_ms),
|
||||
"内存超限".to_string(),
|
||||
)
|
||||
} else if payload.exit_code == Some(0) {
|
||||
("耗时: - · 状态: 成功".to_string(), String::new())
|
||||
(
|
||||
format!("耗时: {}ms · 状态: 成功", payload.duration_ms),
|
||||
String::new(),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
format!("退出码: {} · 运行错误", payload.exit_code.unwrap_or(-1)),
|
||||
format!(
|
||||
"耗时: {}ms · 退出码: {} · 运行错误",
|
||||
payload.duration_ms,
|
||||
payload.exit_code.unwrap_or(-1)
|
||||
),
|
||||
"运行错误".to_string(),
|
||||
)
|
||||
};
|
||||
|
||||
@ -231,7 +231,7 @@ pub async fn run_in_container(
|
||||
|
||||
/// 流式输出 chunk:run_in_container_stream 边读日志边推送给 SSE handler。
|
||||
///
|
||||
/// 序列化后作为 SSE event data;`Done` 同时携带终态信息(退出码 / OOM / 超时)。
|
||||
/// 序列化后作为 SSE event data;`Done` 同时携带终态信息(退出码 / OOM / 超时 / 耗时)。
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum OutputChunk {
|
||||
/// stdout 块(容器逐块产出)。
|
||||
@ -239,10 +239,12 @@ pub enum OutputChunk {
|
||||
/// stderr 块(容器逐块产出)。
|
||||
Stderr(String),
|
||||
/// 终态:容器执行结束。exit_code=None 表示拿不到退出码(wait 出错)。
|
||||
/// duration_ms = start_container 到 wait 完成的耗时。
|
||||
Done {
|
||||
exit_code: Option<i64>,
|
||||
oom_killed: bool,
|
||||
timed_out: bool,
|
||||
duration_ms: u64,
|
||||
},
|
||||
}
|
||||
|
||||
@ -320,6 +322,9 @@ pub async fn run_in_container_stream(
|
||||
.start_container(&container_id, None::<StartContainerOptions>)
|
||||
.await?;
|
||||
|
||||
// 容器开始执行的时刻,用于计算 duration_ms(start_container 返回即视为起点)。
|
||||
let start_time = std::time::Instant::now();
|
||||
|
||||
// 写入源码到 stdin 后关闭 writer。
|
||||
use tokio::io::AsyncWriteExt;
|
||||
let write_fut = async {
|
||||
@ -477,12 +482,14 @@ pub async fn run_in_container_stream(
|
||||
.unwrap_or(false);
|
||||
|
||||
// 推送终态 chunk(客户端已断开则跳过,send 必然失败)。
|
||||
let duration_ms = start_time.elapsed().as_millis() as u64;
|
||||
if !client_disconnected {
|
||||
let _ = tx
|
||||
.send(OutputChunk::Done {
|
||||
exit_code,
|
||||
oom_killed,
|
||||
timed_out,
|
||||
duration_ms,
|
||||
})
|
||||
.await;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user