Leer en inglés

Compartir a través de


Patrón de espera-reintento

En algunas situaciones, el comportamiento de un origen de datos no coincide con el esperado por el control de código HTTP predeterminado de Power Query. Los ejemplos siguientes muestran cómo solucionar esta situación.

En este escenario, trabajará con una API REST que, ocasionalmente, devuelve un código de estado 500, que indica un error interno del servidor. En estos casos, podría esperar unos segundos y volver a intentarlo, potencialmente varias veces antes de desistir.

ManualStatusHandling

Si Web.Contents obtiene una respuesta de código de estado 500, emite un DataSource.Error de forma predeterminada. Para invalidar este comportamiento, proporcione una lista de códigos como argumento opcional para Web.Contents:

response = Web.Contents(url, [ManualStatusHandling={404, 500}])

Al especificar los códigos de estado de esta manera, Power Query seguirá procesando la respuesta web como normal. Sin embargo, el procesamiento normal de respuestas no suele ser adecuado en estos casos. Deberá comprender que se ha recibido un código de respuesta anómalo y realizar una lógica especial para controlarlo. Para determinar el código de respuesta que se devolvió desde el servicio web, puede acceder a él desde el registro meta que acompaña a la respuesta:

responseCode = Value.Metadata(response)[Response.Status]

En función de si responseCode es 200 o 500, puede procesar el resultado como normal o seguir la lógica de espera-reintento que se desarrollará en la sección siguiente.

IsRetry

Power Query tiene una caché local que almacena los resultados de las llamadas anteriores a Web.Contents. Al sondear la misma dirección URL para obtener una respuesta nueva o al realizar un reintento después de un estado de error, deberá asegurarse de que la consulta omita los resultados almacenados en caché. Para ello, incluya la opción IsRetry en la llamada a la función Web.Contents. En este ejemplo, estableceremos IsRetry en true después de la primera iteración del bucle Value.WaitFor.

Value.WaitFor

Value.WaitFor() es una función auxiliar estándar que normalmente se puede usar sin modificaciones. Funciona mediante la creación de una lista de reintentos.

Argumento producer

Contiene la tarea que (posiblemente) se va a reintentar. Se representa como una función para que el número de iteración se pueda usar en la lógica producer. El comportamiento esperado es que producer devolverá null si se determina que es necesario un reintento. Si producer devuelve algo distinto de null, Value.WaitFor devuelve ese valor a su vez.

Argumento delay

Contiene la lógica que se debe ejecutar entre reintentos. Se representa como una función para que el número de iteración se pueda usar en la lógica delay. El comportamiento esperado es que delay devuelva una duración.

Argumento count (opcional)

Se puede establecer un número máximo de reintentos proporcionando un número al argumento count.

En resumen:

En el ejemplo siguiente se muestra cómo ManualStatusHandling y Value.WaitFor se pueden usar para implementar un reintento retrasado en caso de una respuesta 500. El tiempo de espera entre reintentos se duplica con cada intento, con un máximo de cinco reintentos.

let
    waitForResult = Value.WaitFor(
        (iteration) =>
            let
                result = Web.Contents(url, [ManualStatusHandling = {500}, IsRetry = iteration > 0]),
                status = Value.Metadata(result)[Response.Status],
                actualResult = if status = 500 then null else result
            in
                actualResult,
        (iteration) => #duration(0, 0, 0, Number.Power(2, iteration)),
        5)
in
    if waitForResult = null then
        error "Value.WaitFor() Failed after multiple retry attempts"
    else
        waitForResult