Compartir vía


Operaciones de larga duración en Azure SDK para Java

En este artículo se proporciona información general sobre el uso de operaciones de larga duración con Azure SDK para Java.

Ciertas operaciones en Azure pueden tardar mucho tiempo en completarse. Estas operaciones están fuera del estilo HTTP estándar de flujo de solicitud y respuesta rápido. Por ejemplo, la copia de datos desde una dirección URL de origen a un blob de Storage, o el entrenamiento de un modelo para reconocer formularios, son operaciones que pueden tardar desde unos segundos hasta algunos minutos. Dichas operaciones se conocen como operaciones de larga duración y a menudo se abrevian como "LRO". Una LRO puede tardar segundos, minutos, horas, días o más en completarse, en función de la operación solicitada y del proceso que se deba realizar en el servidor.

En las bibliotecas cliente de Java para Azure, existe una convención según la cual todas las operaciones de larga duración comienzan por el prefijo begin. Este prefijo indica que esta operación es de larga duración y que los medios de interacción con esta operación son ligeramente diferentes que el flujo de solicitud y respuesta habitual. Junto con el prefijo begin, el tipo de valor devuelto por la operación también es diferente de lo habitual para habilitar todas las funcionalidades de una operación de larga duración. Como sucede con la mayoría de las cosas en Azure SDK para Java, existen API sincrónicas y asincrónicas para las operaciones de larga duración:

  • En los clientes sincrónicos, las operaciones de larga duración devolverán una instancia de SyncPoller.
  • En los clientes asincrónicos, las operaciones de larga duración devolverán una instancia de PollerFlux.

Tanto SyncPoller como PollerFlux son las abstracciones del lado cliente destinadas a simplificar la interacción con las operaciones de larga duración del servidor. En el resto de este artículo se describen los procedimientos recomendados para trabajar con estos tipos.

Operaciones sincrónicas de larga duración

La llamada a cualquier API que devuelva un elemento SyncPoller iniciará inmediatamente la operación de larga duración. La API devolverá el elemento SyncPoller inmediatamente, lo que le permitirá supervisar el progreso de la operación de larga duración y recuperar el resultado final. En el ejemplo siguiente se muestra cómo supervisar el progreso de una operación de larga duración mediante SyncPoller.

SyncPoller<UploadBlobProgress, UploadedBlobProperties> poller = syncClient.beginUploadFromUri(<URI to upload from>)
PollResponse<UploadBlobProgress> response;

do {
    response = poller.poll();
    System.out.println("Status of long running upload operation: " + response.getStatus());
    Duration pollInterval = response.getRetryAfter();
    TimeUnit.MILLISECONDS.sleep(pollInterval.toMillis());
} while (!response.getStatus().isComplete());

En este ejemplo se usa el método poll() de SyncPoller para recuperar información sobre el progreso de la operación de larga duración. Este código imprime el estado en la consola, pero una mejor implementación tomaría las decisiones pertinentes en función de este estado.

El método getRetryAfter() devuelve información sobre el tiempo que se debe esperar antes del sondeo siguiente. La mayoría de las operaciones de larga duración de Azure devuelven el retraso del sondeo como parte de su respuesta HTTP (por ejemplo, el encabezado retry-after usado habitualmente). Si la respuesta no contiene el retraso del sondeo, el método getRetryAfter() devuelve la duración dada en el momento de invocar la operación de larga duración.

En el ejemplo anterior se usa un bucle do..while para sondear repetidamente hasta que se completa la operación de larga duración. Si no está interesado en estos resultados intermedios, puede llamar a waitForCompletion(). Esta llamada bloqueará el subproceso actual hasta que se complete la operación de larga duración y devuelva la última respuesta de sondeo:

PollResponse<UploadBlobProgress> response = poller.waitForCompletion();

Si la última respuesta de sondeo indica que la operación de larga duración se completó correctamente, puede recuperar el resultado final mediante getFinalResult():

if (LongRunningOperationStatus.SUCCESSFULLY_COMPLETED == response.getStatus()) {
    UploadedBlobProperties result = poller.getFinalResult();
}

Otras API útiles de SyncPoller incluyen:

  1. waitForCompletion(Duration): esperar a que se complete la operación de larga duración para la duración de tiempo de espera especificada.
  2. waitUntil(LongRunningOperationStatus): esperar hasta que se reciba el estado de la operación de larga duración especificada.
  3. waitUntil(LongRunningOperationStatus, Duration): esperar hasta que se reciba el estado de la operación de larga duración especificada o hasta que expire la duración del tiempo de espera especificada.

Operaciones asincrónicas de larga duración

En el ejemplo siguiente se muestra cómo el elemento PollerFlux le permite observar una operación de larga duración. En las API asincrónicas, las llamadas de red se producen en un subproceso diferente al principal que llama a subscribe(). Esto significa que el subproceso principal puede finalizar antes de que el resultado esté disponible. Es responsabilidad suya comprobar que la aplicación no finalice antes de que la operación asincrónica haya tenido tiempo de completarse.

La API asincrónica devuelve un elemento PollerFlux inmediatamente, pero la propia operación de larga duración no se iniciará hasta que se suscriba al elemento PollerFlux. Este proceso es el funcionamiento de todas las API basadas en Flux. En el ejemplo siguiente se muestra una operación asincrónica de larga duración:

asyncClient.beginUploadFromUri(...)
    .subscribe(response -> System.out.println("Status of long running upload operation: " + response.getStatus()));

En el ejemplo siguiente, obtendrá actualizaciones de estado intermitentes en la operación de larga duración. Puede usar estas actualizaciones para determinar si la operación de larga duración sigue funcionando de la manera esperada. Este ejemplo imprime el estado en la consola, pero una mejor implementación tomaría las decisiones de control de errores pertinentes en función de este estado.

Si no está interesado en las actualizaciones de estado intermedias y solo desea recibir notificaciones del resultado final cuando llegue, puede usar código similar al del ejemplo siguiente:

asyncClient.beginUploadFromUri(...)
    .last()
    .flatMap(response -> {
        if (LongRunningOperationStatus.SUCCESSFULLY_COMPLETED == response.getStatus()) {
            return response.getFinalResult();
        }
        return Mono.error(new IllegalStateException("Polling completed unsuccessfully with status: "+ response.getStatus()));
    })
    .subscribe(
        finalResult -> processFormPages(finalResult),
        ex -> countDownLatch.countDown(),
        () -> countDownLatch.countDown());

En este código, el resultado final de la operación de larga duración se recupera mediante una llamada a last(). Esta llamada indica al elemento PollerFlux que desea esperar a que se complete todo el sondeo, momento en el que la operación de larga duración ha alcanzado el estado de finalización y puede inspeccionar su estado para determinar el resultado. Si el sondeador indica que la operación de larga duración se completó correctamente, puede recuperar el resultado final y pasárselo al consumidor en la llamada a subscribe.

Pasos siguientes

Ahora que está familiarizado con las API de larga duración en Azure SDK para Java, consulte Configuración de servidores proxy en Azure SDK para Java para aprender a personalizar más aún el cliente HTTP.