babelforce-manager-sdk 0.45.1

Rust SDK for the babelforce manager APIs — auth, user & agent management, call reporting, metrics, and task automations.
Documentation
//! Pagination helper for v2 list endpoints, which return
//! `{ items: Vec<T>, pagination: Pagination { pages, current, … } }`.
use crate::error::ManagerError;
use crate::retry::{with_retry, RetryPolicy};

/// One fetched page of a v2 list endpoint.
#[derive(Debug, Clone)]
pub struct Page<T> {
    /// The items on this page.
    pub items: Vec<T>,
    /// The 1-based page this response is (the API's `pagination.current`).
    pub page: i32,
    /// Total number of pages.
    pub pages: i32,
    /// Total items across all pages, when the endpoint reports it.
    pub total: Option<i32>,
}

/// Fetch exactly one page. `fetch()` performs the single page request and returns
/// `(items, total_pages, current_page, total_items)`; retried like any idempotent read.
/// The single-page sibling of [`collect_all`] — for callers that surface pagination
/// instead of flattening it.
pub(crate) async fn fetch_page<T, E, F, Fut, M>(
    retry: &RetryPolicy,
    map_err: M,
    fetch: F,
) -> Result<Page<T>, ManagerError>
where
    M: Fn(E) -> ManagerError,
    F: Fn() -> Fut,
    Fut: std::future::Future<Output = Result<(Vec<T>, i32, i32, Option<i32>), E>>,
{
    let (items, pages, current, total) = with_retry(retry, true, fetch).await.map_err(map_err)?;
    Ok(Page {
        items,
        page: current,
        pages,
        total,
    })
}

pub(crate) async fn collect_all<T, E, F, Fut, M>(
    retry: &RetryPolicy,
    map_err: M,
    mut fetch: F,
) -> Result<Vec<T>, ManagerError>
where
    M: Fn(E) -> ManagerError,
    F: FnMut(i32) -> Fut,
    Fut: std::future::Future<Output = Result<(Vec<T>, i32, i32), E>>,
{
    let mut out = Vec::new();
    let mut page = 1;
    loop {
        let (items, pages, _current) = with_retry(retry, true, || fetch(page))
            .await
            .map_err(&map_err)?;
        let empty = items.is_empty();
        out.extend(items);
        // Advance by a local monotonic counter rather than the server-echoed `current`: a server
        // that misreports its cursor (e.g. always returns current=1) can't then spin us in an
        // infinite, memory-exhausting loop. Stop on an empty page or once we reach the page count.
        if empty || page >= pages {
            return Ok(out);
        }
        page += 1;
    }
}