Expose ComfyUI run time on Enhance jobs as run_ms

Parse execution_start vs the end event from /history, store it when the
poller moves a job to ready/failed (never overwritten with null), and
return it as "run_ms" on every job endpoint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Cameron CordesandClaude Opus 5.5 committed 2026-10-30 19:08:48 -04:00
1 parent c7d810b812
commit 47ab6b3c00
9 files changed
+106 -4

No files matched your search

+8
View File
@@ -569,6 +569,8 @@ async fn job_moves_queued_running_ready_and_the_preview_is_relayed() {
fx.svc.poll_once().await;
let (_, j, _) = call(&fx, "GET", &format!("/enhance/jobs/{id}"), None).await;
assert_eq!(j["status"], "ready");
// finished_entry runs 3000 ms before its end timestamp.
assert_eq!(j["run_ms"], 3000);
assert!(j.get("queue_position").is_none());
assert_eq!(j["pending"].as_array().unwrap().len(), 1);
assert_eq!(j["pending"][0]["n"], 0);
@@ -580,6 +582,8 @@ async fn job_moves_queued_running_ready_and_the_preview_is_relayed() {
let (st, _, bytes) = call(&fx, "GET", &uri, None).await;
assert_eq!(st, 200);
assert_eq!(bytes, b"PNG:imageapi_pending_abc.png");
let (_, list0, _) = call(&fx, "GET", &format!("/enhance/jobs?path={PHOTO}"), None).await;
assert_eq!(list0["jobs"][0]["run_ms"], 3000, "list endpoint carries it");
let (st, _, _) = call(&fx, "GET", &format!("/enhance/jobs/{id}/preview/5"), None).await;
assert_eq!(st, 404);
@@ -616,6 +620,9 @@ async fn failed_run_reports_comfys_message() {
.await;
assert_eq!(j["status"], "failed");
assert_eq!(j["error"], "CUDA out of memory");
// No execution_start in that history entry: the field is present but null.
assert!(j.as_object().unwrap().contains_key("run_ms"));
assert!(j["run_ms"].is_null());
}
#[actix_rt::test]
@@ -933,6 +940,7 @@ async fn unreachable_active_jobs_become_unavailable_after_the_grace_period() {
discarded: 0,
created_at: now,
updated_at: now,
run_ms: None,
};
SqliteEnhanceJobDao::from_shared(fx.conn.clone())
.insert(&dao_job)