Como trabalhar com operações de lista

Alguns serviços retornam listas potencialmente grandes de itens, como linhas ou descrições de recursos. Para manter o uso de CPU e uso da memória sob controle, os serviços retornam esses recursos em pages: subconjuntos menores dos itens com um token de continuação para solicitar o próximo subconjunto.

Iterar itens por página pode ser cansativo. As bibliotecas de cliente fornecem adaptadores para converter as páginas em iteradores assíncronos. Este guia mostra como trabalhar com esses adaptadores.

Pré-requisitos

Este guia usa o serviço Secret Manager para demonstrar operações de lista. Os conceitos incluídos neste guia também se aplicam a outros serviços.

Para seguir este guia, você precisa ter ativado o serviço Secret Manager, feito login e garantido que sua conta tenha as permissões necessárias. Para orientações sobre como atender a esses pré-requisitos, siga o guia de início rápido do serviço.

Para instruções completas de configuração das bibliotecas Rust, consulte Como configurar seu ambiente de desenvolvimento.

Dependências

Adicione a biblioteca do Secret Manager ao arquivo Cargo.toml:

cargo add google-cloud-secretmanager-v1

Iteração de métodos de lista

Para ajudar a iterar os itens em um método de lista, as APIs retornam uma implementação da característica ItemPaginator. Introduza a característica no escopo usando uma declaração use:

use google_cloud_gax::paginator::ItemPaginator as _;

Para iterar os itens, use o método 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)
}

Em casos raros, as páginas podem conter informações extras que você precisa acessar, ou talvez seja necessário verificar seu progresso em vários processos. Se necessário, você pode iterar páginas inteiras em vez de itens individuais.

  1. Introduza Paginator no escopo usando uma declaração use:

    use google_cloud_gax::paginator::Paginator as _;

  2. Itere as páginas usando 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));
    }

Trabalhando com futures::Stream

Talvez você queira usar essas APIs no ecossistema Rust maior de fluxos assíncronos, como tokio::Stream. Isso pode ser feito da seguinte forma:

  1. Ative o recurso unstable-streams na caixa google_cloud_gax. O nome desse recurso serve como aviso de que essas APIs são instáveis. Use-as apenas se você estiver preparado para lidar com interrupções resultantes de mudanças incompatíveis na característica futures::Stream.

    cargo add google-cloud-gax --features unstable-stream
    
  2. Os exemplos a seguir também usam a característica futures::stream::StreamExt, que é ativada ao adicionar a caixa futures.

    cargo add futures
    
  3. Adicione as declarações use necessárias:

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

  4. Use a função into_stream para converter ItemPaginator em um 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?;

Da mesma forma, você pode usar a função into_stream para converter Paginator em um 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?;

Retomar métodos de lista definindo o token da próxima página

Em alguns casos, como uma operação de lista interrompida, é possível definir o token da próxima página para retomar a paginação de uma página específica.

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));
}

Quando usar os helpers do paginador

As bibliotecas de cliente Google Cloud para Rust fornecem um adaptador para converter as RPCs de lista, conforme definido por AIP-4233, em tipos que implementam ItemPaginator e Paginator se o método Lista de APIs do Google seguir a diretriz de paginação definida por AIP-158. Em resumo, essa diretriz exige que cada chamada a um método List retorne uma página de itens de recursos (por exemplo, secrets) junto com um token que pode ser transmitido ao método List para recuperar a próxima página.

A maioria dos serviços do Google Cloud segue essas diretrizes. Caso contrário, você precisa implementar seu próprio adaptador para iterar os resultados.