Paginação e iteração no SDK do Azure para Java

Este artigo apresenta uma visão geral de como usar o SDK do Azure para a funcionalidade de paginação e iteração de Java para trabalhar de maneira eficiente e produtiva com grandes conjuntos de dados.

Muitas operações fornecidas pelas bibliotecas de cliente no SDK do Azure para Java retornam mais de um resultado. O SDK do Azure para Java define um conjunto de tipos de retorno aceitáveis nesses casos para garantir que a experiência do desenvolvedor seja maximizada por meio de consistência. Os tipos de retorno usados são PagedIterable para APIs de sincronização e PagedFlux para APIs assíncronas. As APIs diferem um pouco devido a seus diferentes casos de uso, porém, conceitualmente, elas têm os mesmos requisitos:

  • Tornar possível iterar facilmente em cada elemento na coleção individualmente, ignorando qualquer necessidade de paginação manual ou acompanhamento de tokens de continuação. Tanto PagedIterable quanto PagedFlux facilitam essa tarefa ao iterar uma resposta paginada desserializada em um determinado tipo T. PagedIterable implementa a interface Iterable e oferece uma API para receber um Stream, enquanto PagedFlux fornece um Flux. Em todos os casos, o ato de paginação é transparente e a iteração continua enquanto ainda há resultados iterados.

  • Possibilitar a iteração explícita página por página. Isso permite que você entenda com mais clareza quando as solicitações são feitas e acesse informações de resposta por página. Tanto PagedIterable quanto PagedFlux têm métodos que retornarão tipos apropriados para iterar por página, e não por elemento individual.

Este artigo é dividido entre as APIs síncrona e assíncrona do SDK do Azure para Java. Você verá as APIs de iteração síncrona ao trabalhar com clientes síncronos e APIs de iteração assíncrona ao trabalhar com clientes assíncronos.

Paginação síncrona e iteração

Esta seção aborda as APIs síncronas.

Iterar em elementos individuais

Como observado, o caso de uso mais comum é iterar em cada elemento individualmente, em vez de por página. Os exemplos de código a seguir mostram como a API de PagedIterable permite que você use seu estilo de iteração preferido para implementar essa funcionalidade.

Usar um loop for each

Como PagedIterable implementa Iterable, você pode iterar pelos elementos conforme mostra o seguinte exemplo:

PagedIterable<Secret> secrets = client.listSecrets();
for (Secret secret : secrets) {
   System.out.println("Secret is: " + secret);
}

Usar fluxo

Como PagedIterable tem um método stream() definido, você pode chamá-lo para usar as APIs de Fluxo Java padrão, conforme mostra o seguinte exemplo:

client.listSecrets()
      .stream()
      .forEach(secret -> System.out.println("Secret is: " + secret));

Usar iterador

Como o PagedIterable implementa Iterable, ele também tem um método iterator() para permitir o estilo de programação iterador de Java, como mostra o seguinte exemplo:

Iterator<Secret> secrets = client.listSecrets().iterator();
while (it.hasNext()) {
   System.out.println("Secret is: " + it.next());
}

Iterar em páginas

Ao trabalhar com páginas individuais, você pode iterar por página, por exemplo, quando precisa de informações de resposta HTTP ou quando tokens de continuação são importantes para reter o histórico de iteração. Independentemente de você iterar por página ou por item, não há diferença no desempenho nem no número de chamadas feitas ao serviço. A implementação subjacente carrega a próxima página sob demanda e, se você cancelar a assinatura do PagedFlux a qualquer momento, não haverá mais chamadas para o serviço.

Usar um loop for each

Ao chamar listSecrets(), você obtém uma PagedIterable, que tem uma API iterableByPage(). Essa API produz um Iterable<PagedResponse<Secret>>, em vez de um Iterable<Secret>. A PagedResponse fornece os metadados de resposta e o acesso ao token de continuação, conforme mostra o seguinte exemplo:

Iterable<PagedResponse<Secret>> secretPages = client.listSecrets().iterableByPage();
for (PagedResponse<Secret> page : secretPages) {
   System.out.println("Response code: " + page.getStatusCode());
   System.out.println("Continuation Token: " + page.getContinuationToken());
   page.getElements().forEach(secret -> System.out.println("Secret value: " + secret))
}

Há também uma sobrecarga iterableByPage que aceita um token de continuação. Você poderá chamar essa sobrecarga quando quiser retornar ao mesmo ponto de iteração posteriormente.

Usar fluxo

O exemplo a seguir ilustra como o método streamByPage() executa a mesma operação, conforme mostrado acima. Essa API também tem uma sobrecarga de token de continuação para retornar ao mesmo ponto de iteração posteriormente.

client.listSecrets()
      .streamByPage()
      .forEach(page -> {
          System.out.println("Response code: " + page.getStatusCode());
          System.out.println("Continuation Token: " + page.getContinuationToken());
          page.getElements().forEach(secret -> System.out.println("Secret value: " + secret))
      });

Observar páginas e elementos individuais de modo assíncrono

Esta seção aborda as APIs assíncronas. Em APIs assíncronas, as chamadas de rede acontecem em um thread diferente do thread principal que chama subscribe(). Isso significa que o thread principal pode terminar antes que o resultado esteja disponível. Cabe a você garantir que o aplicativo não seja encerrado antes que a operação assíncrona tenha tido tempo para ser concluída.

Observar elementos individuais

O exemplo a seguir mostra como a API de PagedFlux permite observar elementos individuais de modo assíncrono. Há várias maneiras de assinar um tipo Flux. Para obter mais informações, confira Maneiras simples de criar um Flux ou Mono e assiná-lo no Guia de referência do Reactor 3. Este exemplo é uma variedade em que há três expressões lambda, uma de cada para o consumidor, o consumidor de erro e o consumidor completo. Ter as três é uma melhor prática, porém, em alguns casos, só é necessário ter o consumidor e, possivelmente, o consumidor de erro.

asyncClient.listSecrets()
   .subscribe(secret -> System.out.println("Secret value: " + secret),
       ex -> System.out.println("Error listing secrets: " + ex.getMessage()),
       () -> System.out.println("Successfully listed all secrets"));

Observar páginas

O exemplo a seguir mostra como a API de PagedFlux permite que você observe cada página de modo assíncrono, usando uma API de byPage() e fornecendo um consumidor, um consumidor de erro e um consumidor de conclusão.

asyncClient.listSecrets().byPage()
  .subscribe(page -> {
          System.out.println("Response code: " + page.getStatusCode());
          System.out.println("Continuation Token: " + page.getContinuationToken());
          page.getElements().forEach(secret -> System.out.println("Secret value: " + secret))
      },
      ex -> System.out.println("Error listing pages with secret: " + ex.getMessage()),
      () -> System.out.println("Successfully listed all pages with secret"));

Próximas etapas

Agora que você está familiarizado com a paginação e a iteração no SDK do Azure para Java, considere examinar Operações de execução longa no SDK do Azure para Java. Operações de execução longa são operações executadas por uma duração maior do que a maioria das solicitações HTTP normais, geralmente porque exigem algum esforço no lado do servidor.