Wait-Retry パターン

場合によっては、Power Query の 既定の HTTP コード処理で想定される動作とデータ ソースの動作が一致しない場合があります。 次の例は、この状況を回避する方法を示しています。

このシナリオでは、内部サーバー エラーを示す 500 状態コードを時々返す REST API を使用します。 これらのインスタンスでは、数秒待ってから再試行し、場合によっては数回待ってから、あきらめる可能性があります。

手動ステータス管理

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 をポーリングする場合、またはエラー状態の後に再試行する場合は、クエリでキャッシュされた結果が無視されるようにする必要があります。 これを行うには、IsRetry関数の呼び出しに Web.Contents オプションを含めることができます。 このサンプルでは、IsRetry ループの最初のイテレーションの後に、trueを Value.WaitFor に設定します。

Value.WaitFor

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

producer 引数

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

delay 引数

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

count 引数 (省略可能)

count引数に数値を指定することで、再試行の最大数を設定できます。

すべてをまとめる

次の例は、 ManualStatusHandling と Value.WaitFor を使用して、500 応答が発生した場合に遅延再試行を実装する方法を示しています。 再試行の間の待機時間は、再試行ごとに 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