StepFunctions の Waitステートによる Lambda の遅延実行

渡辺です。 こういった小技、意外と検索しても出てこないですね。

一定時間または特定日時に処理を実行したい

Lambdaを 定期実行 するには、cronのように設定できる CloudWatch Eventsが便利です。 一方、 特定時間後 、もしくは 特定日時1回だけ Lambdaを実行したいこともあります。 例えば、注文を受けて一定時間後に自動キャンセル、ブログの時限投稿などです。

このようなユースケースでは、Step Functions の Waitステートがベストです。

Wait ステート

Step FunctionsのWait ステートは、名前の通り、待機状態を作るステートです。 実行がWait ステートの時、料金は一切かかりません(厳密には状態遷移に料金はかかるが、1,000 回の状態遷移あたり 0.025 USD)。 待機時間は、最大で約1年待機することができます(厳密には全体の実行時間が合計1年まで)。 おまけに、待機時間は相対時間でも絶対時間でも指定できます!

ステートマシンの例

この例は、待機時間をパラメータとして受け取り、待機後にLambdaを実行するステートマシンです。

{
  "StartAt": "Wait",
  "States": {
    "Wait": {
      "Type": "Wait",
      "SecondsPath": "$.wait_secs",
      "Next": "MainTask"
    },
    "MainTask": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxxx:function:main_task",
      "End": true
    }
  }
}

入力パラメータの wait_secs 秒を待機し、 main_task 関数を実行します。

SecondsPath は入力パラメータから相対時間(秒)を指定し、 Seconds はステートマシンに待機する絶対時間を設定します。 そして、 TimestampPath は入力パラメータから絶対日時を指定できます。 あまり使い道はありませんが、 Timestamp を使い絶対日時を指定することもできます。

ステートマシンの起動

ステートマシンを起動するには、ステートマシンのARNと初期入力値を与えて、startExecution を実行します。

const AWS = require('aws-sdk');
const StepFunctions = new AWS.StepFunctions();

const input = {
    wait_secs: 60 * 20, // 20 minitues
    other_param: 'Hello World'
};
const params = {
    stateMachineArn: `arn:aws:states:ap-northeast-1:xxxxxxxxxxxxx:stateMachine:main_task_after_wait`,
    input: JSON.stringify(input)
};
await StepFunctions.startExecution(params).promise();
};

まとめ

一定時間後に処理を実行するというのは、DBなどを利用してスケジューリングもできますが、とてつもなく面倒です。 AWSであれば、CloudWatch Eventsを作成して実行させることもできますが、 Step Function は、非常にシンプルに、低コストで実現できます。 また、リトライや処理失敗時のフォールバック処理も可能です。

なお、待機時間はステートマシンに固定することも、パラメータで与えることもできます。 詳しくはドキュメントを参照ください。