feat(admin): observability — job history, live now-analyzing, durations & metrics (0.84.0) (#6)
Some checks failed
deploy / test-backend (push) Failing after 19m59s
deploy / test-frontend (push) Successful in 9m54s
deploy / build-and-push (push) Has been skipped
deploy / deploy (push) Has been skipped

This commit was merged in pull request #6.
This commit is contained in:
2026-06-16 12:21:13 +00:00
parent 790549636f
commit d51ab2a049
41 changed files with 3655 additions and 21 deletions

View File

@@ -60,6 +60,27 @@ pub async fn locate(
Ok(row)
}
/// Like [`locate`] but also resolves the manga title and chapter number, so
/// live analysis events can carry human labels for the "now analyzing"
/// banner without the dashboard having to look them up. Returns
/// `(manga_id, manga_title, chapter_id, chapter_number, page_number)`.
pub async fn locate_labeled(
pool: &PgPool,
page_id: Uuid,
) -> AppResult<Option<(Uuid, String, Uuid, i32, i32)>> {
let row: Option<(Uuid, String, Uuid, i32, i32)> = sqlx::query_as(
"SELECT c.manga_id, m.title, p.chapter_id, c.number, p.page_number \
FROM pages p \
JOIN chapters c ON c.id = p.chapter_id \
JOIN mangas m ON m.id = c.manga_id \
WHERE p.id = $1",
)
.bind(page_id)
.fetch_optional(pool)
.await?;
Ok(row)
}
pub async fn list_for_chapter(pool: &PgPool, chapter_id: Uuid) -> AppResult<Vec<Page>> {
let rows = sqlx::query_as::<_, Page>(
r#"