#分页 #页面 #分页的

page-turner

分页 API 的一般抽象

4 个版本 (1 个稳定版)

1.0.0 2024年1月15日
0.8.2 2022年10月17日
0.7.0 2022年10月12日
0.6.0 2022年10月7日

#107 in 异步

Download history 585/week @ 2024-03-31 425/week @ 2024-04-07 520/week @ 2024-04-14 466/week @ 2024-04-21 482/week @ 2024-04-28 114/week @ 2024-05-05 465/week @ 2024-05-12 1166/week @ 2024-05-19 1012/week @ 2024-05-26 731/week @ 2024-06-02 366/week @ 2024-06-09 529/week @ 2024-06-16 537/week @ 2024-06-23 670/week @ 2024-06-30 487/week @ 2024-07-07 441/week @ 2024-07-14

2,167 每月下载量
用于 prelate-rs

MIT/Apache

72KB
1.5K SLoC

Build

page-turner

分页 API 的一般抽象

简而言之

如果您有一个分页请求,请在该请求的客户端实现 page-turner 特性

use page_turner::prelude::*;

impl PageTurner<GetReviewsRequest> for ApiClient {
    type PageItems = Vec<Review>;
    type PageError = ApiError;

    async fn turn_page(&self, request: GetReviewsRequest) -> TurnedPageResult<Self, GetReviewsRequest> {
        let response = self.execute(request).await?;

        let turned_page = match response.next_page_token {
            Some(token) => TurnedPage::next(response.reviews, GetReviewsRequest::from(token)),
            None => TurnedPage::last(response.reviews),
        };

        Ok(turned_page)
    }
}

然后 page-turner 提供基于流的 API,允许像不存在分页一样查询数据

use page_turner::prelude::*;
use futures::{StreamExt, TryStreamExt};

async fn first_n_positive_reviews(client: &ApiClient, request: GetReviewsRequest, count: usize) -> ApiResult<Vec<Review>> {
    client
        .pages(request)
        .items()
        .try_filter(|review| std::future::ready(review.is_positive()))
        .take(count)
        .await
}

支持游标和非游标分页模式,对于后者,您可以通过实现 RequestAhead 特性来启用并发查询

pub struct GetCommentsRequest {
    pub page_id: PageId,
}

impl RequestAhead for GetCommentsRequest {
    fn next_request(&self) -> Self {
        Self {
            page_id: self.page_id + 1,
        }
    }
}

现在您可以使用 pages_ahead/pages_ahead_unordered 系列方法并发请求多个页面,底层使用非常优化的 滑动窗口 请求调度

use page_turner::prelude::*;
use futures::TryStreamExt;

async fn retrieve_user_comments(username: &str) -> ResponseResult<Vec<Comment>> {
    let client = ForumClient::new();

    client.pages_ahead(4, Limit::None, GetCommentsRequest { page_id: 1 })
        .items()
        .try_filter(|comment| std::future::ready(comment.author == username))
        .try_collect()
        .await

}

上面的例子同时安排了 4 个页面的请求,并在您收到响应的同时立即发出请求,在整个处理结果的过程中始终等待 4 个响应。

v1.0.0 版本发布

v1.0.0 使用 Rust 1.75 中稳定的 RPITIT 等特性,因此 v1.0.0 的 MSRV 是 1.75.0。如果您无法升级到 Rust 1.75,请使用该包的 0.8.2 版本。它与后者非常相似,并支持 Rust 版本,与 async_trait 包支持的版本相同。

有关新支持功能详情,请参阅 文档

有关完整更改历史,请参阅 CHANGELOG.md

从旧版本迁移到v1.0.0

v1.0.0中有几个主要的重大变更,以下是快速适应它们的说明

  1. 默认情况下不再需要#[async_trait]。从您的翻页器实现中移除#[async_trait],一切应该都会正常工作。如果您出于某种原因依赖于dyn PageTurner,则启用功能dynamic并使用page_turner::dynamic::prelude::*代替page_turner::prelude::*

  2. 新的翻页器不再强制要求您返回Vec<PageItem>,现在您可以返回任何您喜欢的(例如HashMap是一个流行的替代方案之一)。为了快速使您的代码编译并保留旧的行为,将type PageItem = YourItem;替换为type PageItems = Vec<YourItem>;。注意PageItems中的s:()

  3. PageTurnerOutput已被重命名为TurnedPageResult,但它是一个相同的类型别名,因此简单的全局搜索和替换应该就可以解决问题。

  4. into_pages_aheadinto_pages_ahead_unordered方法现在要求实现者可克隆。以前,它们在内部使用Arc,但现在由您决定。您的客户端可能已经是廉价可克隆的,如果不是的话,快速解决Clone错误的方法是将客户端包裹在Arc中,如Arc::new(client).into_pages_ahead(..)

许可

根据您的选择,在Apache License, Version 2.0MIT license下许可。

除非您明确声明,否则根据Apache-2.0许可中定义的,您有意提交的任何贡献,包括但不限于以下内容,都应双重许可,如上所述,没有附加条款或条件。

依赖项

~0.6–1MB
~18K SLoC