Files
Mangalord/backend/src/api/pagination.rs
MechaCat02 ebf0b8289b fix: compute the /mangas total only on the first page
GET /mangas recomputed count(*) over FILTER_WHERE (up to five correlated
subqueries) on every page, so pagination cost scaled with catalog size. The
total doesn't change as a caller walks pages, so compute it once at offset 0
and return null thereafter (the envelope already serialises total as
Option<i64>; the frontend types it number|null and the library route ignores
it).

Bump to 0.124.7.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 21:14:15 +02:00

52 lines
1.3 KiB
Rust

//! Shared pagination envelope for list endpoints.
//!
//! `total` is `Option<i64>` and is always serialised — `null` when the
//! handler hasn't computed it yet, a number once it has. The shape is fixed
//! across `/mangas`, `/chapters`, `/bookmarks`, etc. so consumers can
//! handle pagination uniformly.
use serde::Serialize;
#[derive(Debug, Serialize)]
pub struct PageInfo {
pub limit: i64,
pub offset: i64,
pub total: Option<i64>,
}
#[derive(Debug, Serialize)]
pub struct PagedResponse<T> {
pub items: Vec<T>,
pub page: PageInfo,
}
impl<T> PagedResponse<T> {
pub fn new(items: Vec<T>, limit: i64, offset: i64) -> Self {
Self {
items,
page: PageInfo { limit, offset, total: None },
}
}
pub fn with_total(items: Vec<T>, limit: i64, offset: i64, total: i64) -> Self {
Self {
items,
page: PageInfo { limit, offset, total: Some(total) },
}
}
/// For handlers that compute `total` only on some pages (e.g. the first)
/// and leave it `None` elsewhere.
pub fn with_optional_total(
items: Vec<T>,
limit: i64,
offset: i64,
total: Option<i64>,
) -> Self {
Self {
items,
page: PageInfo { limit, offset, total },
}
}
}