待機-再試行パターン

状況によっては、データ ソースの動作が Power Query のデフォルトの HTTP コード処理で期待される動作と一致しないことがあります。 以下の例は、この状況を回避する方法を示しています。

このシナリオでは、内部サーバー エラーを示す 500 ステータス コードを返す REST API を使用します。 このような場合は、数秒待ってから再試行してください。数回行う必要があるかもしれません。

ManualStatusHandling

Web.Contents が 500 状態コードの応答を受け取ると、既定で DataSource.Error をスローします。 Web.Contents のオプションの引数としてコードのリストを提供することで、この動作をオーバーライドできます。

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

このように状態コードを指定することで、Power Query は通常どおり Web 応答を処理し続けます。 ただし、これらの場合、通常の応答処理は適切でないことが多いです。 異常な応答コードを受信したことを理解して、処理するための特別なロジックを実行する必要があります。 Web サービスから返された応答コードを判別するには、応答に付随する meta レコードからアクセスできます。

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

responseCode が 200 または 500 のどちらであるかに基づいて、結果を通常どおりに処理します。または、次のセクションで説明する、待機-再試行ロジックに従います。

IsRetry

Power Query には、Web.Contents への以前の呼び出しの結果を保存するローカル キャッシュがあります。 新しい応答を求めて同じ URL をポーリングする場合、またはエラー ステータスの後に再試行する場合は、キャッシュされた結果がクエリで無視されるようにする必要があります。 これを行うには、Web.Contents 関数の呼び出しに IsRetryオプションを含めます。 このサンプルでは、Value.WaitForループの最初の反復後に IsRetrytrueに設定します。

Value.WaitFor

Value.WaitFor() は、通常は変更不要で使用できる標準のヘルパー関数です。 これは、再試行のリストを作成することによって機能します。

producer 引数

これには、タスクが含まれています。これらのタスクは、(場合によっては) 再試行されます。 producer ロジックで反復回数を使用できるように、関数として表されます。 想定される動作は、再試行が必要であると判断された場合に producernull を返すことです。 null 以外のものが producer によって返される場合、その値は順番に Value.WaitFor によって返されます。

delay 引数

これには、再試行の間に実行するロジックが含まれています。 delay ロジックで反復回数を使用できるように、関数として表されます。 想定される動作は、delay が Duration を返すことです。

count 引数 (省略可能)

再試行の上限回数は、count 引数に数値を指定することで設定できます。

まとめ

次の例は、500 応答の場合に、ManualStatusHandling および Value.WaitFor を使用して、遅延の再試行を実装する方法を示しています。 再試行間の待機時間は試行ごとに 2 倍になり、最大 5 回の再試行が可能です。

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