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.
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.
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()
es una función auxiliar estándar que normalmente se puede usar sin modificaciones. Funciona mediante la creación de una lista de reintentos.
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.
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.
Se puede establecer un número máximo de reintentos proporcionando un número al argumento count
.
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