使用列表操作

某些服务会返回可能包含大量项的列表,例如行或资源说明。为了控制 CPU 和内存用量,服务会以 pages 的形式返回这些资源:包含续航令牌的较小子集,用于请求下一个子集。

按网页迭代处理商品可能很麻烦。客户端库提供适配器,用于将网页转换为异步迭代器。本指南介绍了如何使用这些适配器。

前提条件

本指南使用 Secret Manager 服务来演示列表操作。本指南中包含的概念也适用于其他服务。

若要遵照本指南操作,您需要已启用 Secret Manager 服务、已登录,并确保您的账号拥有必要的权限。如需有关如何满足这些前提条件的指导,请参阅服务快速入门

如需查看 Rust 库的完整设置说明,请参阅设置开发环境

依赖项

将 Secret Manager 库添加到您的 Cargo.toml 文件中:

cargo add google-cloud-secretmanager-v1

迭代列表方法

为了帮助迭代列表方法中的项,API 会返回 ItemPaginator 特征的实现。使用 use 声明将特征引入作用域:

use google_cloud_gax::paginator::ItemPaginator as _;

如需迭代处理这些项,请使用 by_item 方法。

let mut list = client
    .list_secrets()
    .set_parent(format!("projects/{project_id}"))
    .by_item();
while let Some(secret) = list.next().await {
    let secret = secret?;
    println!("  secret={}", secret.name)
}

在极少数情况下,网页可能包含您需要访问的额外信息,或者您可能需要在不同进程中检查进度。如果需要,您可以迭代整个页面,而不是单个商品。

  1. 使用 use 声明将 Paginator 引入作用域:

    use google_cloud_gax::paginator::Paginator as _;

  2. 使用 by_page 遍历网页:

    let mut list = client
        .list_secrets()
        .set_parent(format!("projects/{project_id}"))
        .by_page();
    while let Some(page) = list.next().await {
        let page = page?;
        println!("  next_page_token={}", page.next_page_token);
        page.secrets
            .into_iter()
            .for_each(|secret| println!("    secret={}", secret.name));
    }

使用 futures::Stream

您可能希望在更大的 Rust 异步流生态系统中使用这些 API,例如 tokio::Stream。您可以通过以下方式实现这一目标:

  1. google_cloud_gax crate 中启用 unstable-streams 功能。此功能的名称表明这些 API 不稳定。只有在您准备好应对因 futures::Stream 特征发生不兼容的更改而导致的任何中断时,才应使用这些方法。

    cargo add google-cloud-gax --features unstable-stream
    
  2. 以下示例还使用了 futures::stream::StreamExt 特征,您可以通过添加 futures crate 来启用该特征。

    cargo add futures
    
  3. 添加所需的 use 声明:

    use futures::stream::StreamExt;
    use google_cloud_gax::paginator::ItemPaginator as _;

  4. 使用 into_stream 函数将 ItemPaginator 转换为 futures::Stream

    let list = client
        .list_secrets()
        .set_parent(format!("projects/{project_id}"))
        .by_item()
        .into_stream();
    list.map(|secret| -> gax::Result<()> {
        println!("  secret={}", secret?.name);
        Ok(())
    })
    .fold(Ok(()), async |acc, result| -> gax::Result<()> {
        acc.and(result)
    })
    .await?;

同样,您可以使用 into_stream 函数将 Paginator 转换为 futures::Stream

let list = client
    .list_secrets()
    .set_parent(format!("projects/{project_id}"))
    .by_page()
    .into_stream();
list.enumerate()
    .map(|(index, page)| -> gax::Result<()> {
        println!("page={}, next_page_token={}", index, page?.next_page_token);
        Ok(())
    })
    .fold(Ok(()), async |acc, result| -> gax::Result<()> {
        acc.and(result)
    })
    .await?;

通过设置下一页令牌恢复列表方法

在某些情况下(例如列表操作中断),您可以设置下一页令牌,以便从特定页面恢复分页。

let page = client
    .list_secrets()
    .set_parent(format!("projects/{project_id}"))
    .send()
    .await;
let page = page?;
let mut next_page_token = page.next_page_token.clone();
page.secrets
    .into_iter()
    .for_each(|secret| println!("    secret={}", secret.name));

while !next_page_token.is_empty() {
    println!("  next_page_token={next_page_token}");

    let page = client
        .list_secrets()
        .set_parent(format!("projects/{project_id}"))
        .set_page_token(next_page_token)
        .send()
        .await;
    let page = page?;
    next_page_token = page.next_page_token.clone();

    page.secrets
        .into_iter()
        .for_each(|secret| println!("    secret={}", secret.name));
}

何时使用分页器辅助函数

Google Cloud Rust 客户端库提供了一个适配器,用于将 AIP-4233 定义的列表 RPC 转换为实现 ItemPaginatorPaginator 的类型(如果 Google API 列表方法遵循 AIP-158 定义的分页指南)。简而言之,此指南要求每次调用 List 方法时,都返回一页资源项(例如密钥),以及一个可传递给 List 方法以检索下一页的令牌。

大多数 Google Cloud 服务都遵循这些准则。如果不是,您必须实现自己的适配器来迭代结果。