Cómo trabajar con operaciones de lista

Algunos servicios muestran listas de elementos potencialmente grandes, como filas o descripciones de recursos. Para mantener bajo control el uso de CPU y memoria, los servicios muestran estos recursos en pages: subconjuntos más pequeños de los elementos con un token de continuación para solicitar el siguiente subconjunto.

Iterar sobre los elementos por página puede ser tedioso. Las bibliotecas cliente proporcionan adaptadores para convertir las páginas en iteradores asíncronos. En esta guía, se muestra cómo trabajar con estos adaptadores.

Requisitos previos

En esta guía, se usa el servicio de Secret Manager para demostrar las operaciones de lista. Los conceptos incluidos en esta guía también se aplican a otros servicios.

Para seguir esta guía, deberás habilitar el servicio de Secret Manager, acceder y asegurarte de que tu cuenta tenga los permisos necesarios. Para obtener orientación sobre cómo cumplir con estos requisitos previos, sigue la guía de inicio rápido del servicio .

Para obtener instrucciones de configuración completas para las bibliotecas de Rust, consulta Configura tu entorno de desarrollo.

Dependencias

Agrega la biblioteca de Secret Manager a tu archivo Cargo.toml:

cargo add google-cloud-secretmanager-v1

Iteración de métodos de lista

Para ayudar a iterar los elementos en un método de lista, las APIs muestran una implementación del rasgo ItemPaginator. Introduce el rasgo en el alcance con una declaración use:

use google_cloud_gax::paginator::ItemPaginator as _;

Para iterar sobre los elementos, usa el 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)
}

En casos poco comunes, es posible que las páginas contengan información adicional a la que necesitas acceder o que debas marcar tu progreso en los procesos. Si es necesario, puedes iterar sobre páginas completas en lugar de elementos individuales.

  1. Introduce Paginator en el alcance con una declaración use:

    use google_cloud_gax::paginator::Paginator as _;

  2. Itera sobre las páginas con 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));
    }

Trabaja con futures::Stream

Es posible que desees usar estas APIs en el ecosistema más grande de Rust de flujos asíncronos, como tokio::Stream. Esto se logra de la siguiente manera:

  1. Habilita la función unstable-streams en el crate google_cloud_gax. El nombre de esta función sirve como aviso de que estas APIs son inestables. Solo debes usarlas si estás preparado para lidiar con cualquier interrupción que resulte de cambios incompatibles en el futures::Stream rasgo.

    cargo add google-cloud-gax --features unstable-stream
    
  2. En los siguientes ejemplos, también se usa el rasgo futures::stream::StreamExt, que se habilita agregando el crate futures.

    cargo add futures
    
  3. Agrega las declaraciones use obligatorias:

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

  4. Usa la función into_stream para convertir ItemPaginator en un 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?;

Del mismo modo, puedes usar la función into_stream para convertir Paginator en un 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?;

Reanuda los métodos de lista configurando el token de página siguiente

En algunos casos, como una operación de lista interrumpida, puedes configurar el token de página siguiente para reanudar la paginación desde una 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));
}

Cuándo usar los asistentes de paginador

Las Google Cloud bibliotecas cliente de Rust proporcionan un adaptador para convertir las RPC de lista según lo definido por AIP-4233 en tipos que implementan ItemPaginator y Paginator si el método de lista de la API de Google sigue el lineamiento de paginación definido por AIP-158. En resumen, este lineamiento requiere que cada llamada a un método List muestre una página de elementos de recursos (por ejemplo, secretos) junto con un token que puedes pasar al método List para recuperar la página siguiente.

Lamayoría de los Google Cloud servicios siguen estos lineamientos. En los casos en los que no lo hacen, debes implementar tu propio adaptador para iterar sobre los resultados.