feat(admin): observability — job history, live now-analyzing, durations & metrics (0.84.0) (#6)
This commit was merged in pull request #6.
This commit is contained in:
@@ -216,16 +216,23 @@ impl WorkerContext {
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve the page breadcrumb once so live events carry the
|
||||
// manga/chapter/number the dashboard keys on. A missing breadcrumb
|
||||
// (page deleted) just suppresses events — the dispatch still runs
|
||||
// and acks normally.
|
||||
let breadcrumb = repo::page::locate(&self.pool, page_id).await.ok().flatten();
|
||||
if let Some((manga_id, chapter_id, page_number)) = breadcrumb {
|
||||
// Resolve the labeled page breadcrumb once so live events carry the
|
||||
// manga/chapter/number AND human labels the dashboard's "now
|
||||
// analyzing" banner names. A missing breadcrumb (page deleted) just
|
||||
// suppresses events — the dispatch still runs and acks normally.
|
||||
let breadcrumb = repo::page::locate_labeled(&self.pool, page_id)
|
||||
.await
|
||||
.ok()
|
||||
.flatten();
|
||||
if let Some((manga_id, manga_title, chapter_id, chapter_number, page_number)) =
|
||||
breadcrumb.clone()
|
||||
{
|
||||
self.events.publish(AnalysisEvent::Started {
|
||||
page_id,
|
||||
manga_id,
|
||||
manga_title,
|
||||
chapter_id,
|
||||
chapter_number,
|
||||
page_number,
|
||||
});
|
||||
}
|
||||
@@ -246,8 +253,10 @@ impl WorkerContext {
|
||||
})
|
||||
};
|
||||
|
||||
let started = std::time::Instant::now();
|
||||
let dispatch = AssertUnwindSafe(self.dispatcher.dispatch(page_id)).catch_unwind();
|
||||
let outcome = tokio::time::timeout(self.job_timeout, dispatch).await;
|
||||
let elapsed_ms = started.elapsed().as_millis() as i64;
|
||||
heartbeat.abort();
|
||||
|
||||
// Flatten timeout / panic / dispatch error into one Result + message.
|
||||
@@ -258,11 +267,27 @@ impl WorkerContext {
|
||||
Ok(Ok(Ok(()))) => Ok(()),
|
||||
};
|
||||
|
||||
if let Some((manga_id, chapter_id, page_number)) = breadcrumb {
|
||||
if let Some((manga_id, manga_title, chapter_id, chapter_number, page_number)) =
|
||||
breadcrumb
|
||||
{
|
||||
let event = if result.is_ok() {
|
||||
AnalysisEvent::Completed { page_id, manga_id, chapter_id, page_number }
|
||||
AnalysisEvent::Completed {
|
||||
page_id,
|
||||
manga_id,
|
||||
manga_title,
|
||||
chapter_id,
|
||||
chapter_number,
|
||||
page_number,
|
||||
}
|
||||
} else {
|
||||
AnalysisEvent::Failed { page_id, manga_id, chapter_id, page_number }
|
||||
AnalysisEvent::Failed {
|
||||
page_id,
|
||||
manga_id,
|
||||
manga_title,
|
||||
chapter_id,
|
||||
chapter_number,
|
||||
page_number,
|
||||
}
|
||||
};
|
||||
self.events.publish(event);
|
||||
}
|
||||
@@ -294,6 +319,11 @@ impl WorkerContext {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stamp how long the vision dispatch took. Best-effort and ordered
|
||||
// after the row is written (persist on success / mark_failed on
|
||||
// terminal failure); a transient failure with no row updates nothing.
|
||||
let _ = repo::page_analysis::record_duration(&self.pool, page_id, elapsed_ms).await;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user