コンテンツにスキップ

RetryableError

Craft FunctionsではRetryableError という特別なエラークラスを使って例外を発生させることで、ファンクションの自動的な再実行が行えます。外部サービスの一時的なエラーやネットワークエラーが発生した場合に利用できます。

ファンクション再実行の仕様

次の仕様でファンクションの再実行が行われます。

  • ファンクション内で RetryableError() を使って例外を投げると、ファンクションの再実行が行われます。
  • 再実行は、そのファンクションが正常終了するかRetryableError() 以外のエラーで異常終了するまで繰り返し行われます。
  • 再実行の間隔は指数バックオフ(Exponential Backoff)で決まります。そのため、繰り返しの回数が増えるほど再実行間の待機時間は長くなります。
  • ファンクションの再実行は初回起動時から最大で86400秒 (1日) 繰り返します。
    • RetryableError() を発生させる際にコンストラクタの第2引数 (retryThresholdAge) を指定した場合はその秒数まで再実行を繰り返します。
    • retryThresholdAge は0から86400までの範囲で指定できます。86400より大きな値を指定した場合は最大値として扱われます。

利用方法

RetryableError() の利用方法を説明します。

RetryableError() でファンクションを再実行する

RetryableErrorMODULES に含まれています。例として、次のように RetryableError を投げることができます。ここでは例として50%の確率で再実行していますが、実際には外部サービスへのリクエストのように、ファンクションの再実行が有効な場面で使用します。

export default async function( data, { MODULES } ) {
const { RetryableError } = MODULES;
// 50%の確率で再実行
if (Math.random() > 0.5) {
throw new RetryableError('test retry');
}
}

再実行の期限を設定する

RetryableError() では再実行の期限が設定できます。第2引数 (retryThresholdAge) を指定することで、ファンクションの実行要求が出たタイミングからその秒数までファンクションを再実行します。次の例では retryThresholdAge = 3600 を指定することで再実行の期限を1時間に制限しています。

export default async function( data, { MODULES } ) {
const { RetryableError } = MODULES;
if (Math.random() > 0.5) {
// 再実行を最大1時間=3600秒繰り返す
throw new RetryableError('test retry', 3600);
}
}

ベストプラクティス

  • ファンクションの再実行は一時的なエラーに対するリトライのために使用してください。実装のバグによって必ずエラーとなる場合に RetryableError() を投げると retryThresholdAge で指定した期限まで再実行が繰り返されるので注意してください。
  • 再実行を使う場合、ファンクションはべき等(同じ操作に対して必ず同じ結果が得られる性質)になるように実装してください。べき等ではない場合、再実行の有無によって得られる結果が変わってしまいます。

FAQ

よくある質問と回答です。

Q. 再実行したファンクションはファンクションの実行回数に加算されますか?

はい。再実行したファンクションもファンクションの実行回数として加算されます。

Q. Craft Endpointへのリクエスト時にエラーになった場合はどうなりますか。

RetryableErrorによる例外が発生した場合、Craft Endpointは200ステータスで {} を返却します。

Q. HTTPタイプのファンクションでもリトライできますか?

いいえ、イベント駆動タイプのファンクションでしかRetryableErrorを使ったリトライは利用できません。

「HTTPタイプのファンクション」内の処理の一部をリトライしたい場合は、リトライ対象の処理だけを担う「イベント駆動タイプのファンクション」を別で作成し、Craft Functionsから実行する機能を使って「HTTPタイプのファンクション」からそのファンクションを呼び出してください。 そうすることで、「イベント駆動タイプのファンクション」側でRetryableErrorを使った処理のリトライが可能になります。

APIリファレンス

リファレンス