feat(storage): admin storage-usage stats + per-manga/chapter sizes
Persist blob sizes (covers + chapter pages) and surface upload storage usage to admins in two places: - Admin System tab: total/covers/chapters totals, ratio of disk, average image sizes, and top-5 largest mangas/chapters leaderboards, behind a new GET /api/v1/admin/storage endpoint (separate from /admin/system so the cheap DB aggregates aren't coupled to its 250ms CPU sample). - Manga detail page: total chapter-content size and per-chapter size, with an em-dash for uncrawled or not-yet-measured chapters. Sizes are captured at write time (crawler put_stream return, uploaded page/cover byte length) into nullable pages.size_bytes / mangas.cover_size_bytes columns; NULL means "not yet measured", distinct from a real 0. A one-shot, idempotent admin "Backfill sizes" action (POST /api/v1/admin/storage/backfill) stats pre-existing blobs in keyset-paginated, capped batches and reports more_remaining so a large legacy library can be drained over multiple runs. Aggregates and leaderboards treat NULL honestly (only fully-measured entities are ranked); a dashboard banner flags unmeasured rows so partial figures aren't read as complete. persist_pages now prunes stale page rows on a shrinking re-crawl so totals and page_count stay consistent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,7 @@ struct ChapterUploadRow {
|
||||
title: Option<String>,
|
||||
page_count: i32,
|
||||
created_at: chrono::DateTime<chrono::Utc>,
|
||||
size_bytes: Option<i64>,
|
||||
}
|
||||
|
||||
/// Returns up to `limit` of the user's most recent uploads (mangas and
|
||||
@@ -64,7 +65,13 @@ pub async fn list_for_user(
|
||||
c.number,
|
||||
c.title,
|
||||
c.page_count,
|
||||
c.created_at
|
||||
c.created_at,
|
||||
(SELECT CASE
|
||||
WHEN count(*) = 0 THEN 0
|
||||
WHEN bool_or(p.size_bytes IS NULL) THEN NULL
|
||||
ELSE sum(p.size_bytes)
|
||||
END
|
||||
FROM pages p WHERE p.chapter_id = c.id)::bigint AS size_bytes
|
||||
FROM chapters c
|
||||
JOIN mangas m ON m.id = c.manga_id
|
||||
WHERE c.uploaded_by = $1
|
||||
@@ -97,6 +104,7 @@ pub async fn list_for_user(
|
||||
title: c.title,
|
||||
page_count: c.page_count,
|
||||
created_at: c.created_at,
|
||||
size_bytes: c.size_bytes,
|
||||
},
|
||||
created_at,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user