StepFunctions で指定時刻まで処理を待機させる方法

StepFunctions で指定時刻まで処理を待機させる方法

Wait 状態にて Timestamp をご利用いただくことで時間指定で待機を行うことが可能です。
Clock Icon2024.08.06

困っていること

StepFunctions の処理を特定の状態で指定した時刻まで待機させたいです。
どのように設定すれば可能でしょうか。

どう対応すればいいの?

Wait 状態にて Timestamp をご利用いただくことで時間指定で待機を行うことが可能です。

Wait 状態では待機時間の指定に Seconds フィールドおよび Timestamp フィールドをご利用いただけます。
Seconds フィールドは指定した秒数待機するものとなりますが、
Timestamp フィールドはフィールドに指定された絶対時間まで待機を行うフィールドとなります。

https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/amazon-states-language-wait-state.html

Timestamp
Next フィールドで指定された状態の開始を待機する絶対時間。

タイムスタンプは、ISO 8601 の RFC3339 プロファイルに従う必要があります。
ただし、大文字の T によって日付部分と時刻部分を区切り、大文字の Z によって数値のタイムゾーンオフセットが存在しないことを示す必要があるという追加の制限があります。
例えば、2024-08-18T17:33:00Z などです。

また、Wait 状態の各種パラメータは前状態から入力値として与えることで実行中に任意の値を設定することが可能です。
前状態に、Lambda 関数を実行する状態等を配置いただくことで、実行開始後に指定した任意の時間まで待機させるような実装を行うことも可能となります。

https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/amazon-states-language-wait-state.html#wait-state-example

待機時間をハードコードする必要はありません。

やってみた

実際に前状態の Lambda 関数から待機時刻を取得し、指定された時刻まで処理を待機する StepFunctions を作成してみます。

まずは、Lambda 関数が実行開始された時間から 1 分後の時間をレスポンスとして返却する Lambda 関数を作成します。
ソースコードは以下の通りです。

import json
import boto3
import datetime

sfn = boto3.client('stepfunctions')

def lambda_handler(event, context):
    # StepFunctions から送信されたトークンを取得
    token = event.get("token") 
    # 現在時刻を取得し ISO8601 に変換
    dt1 = datetime.datetime.now()
    dt2 = dt1 + datetime.timedelta(minutes=1)
    utc = dt2.strftime("%Y-%m-%dT%H:%M:%SZ")
    # 結果の送信
    sfn.send_task_success(
        taskToken=token,
        output=json.dumps({
            "expirydate": utc
        })
    )

本来ならばエラー処理など諸々加えなければいけない処理がありますが、実験用のためご容赦ください。
ステートマシンは以下の内容で作成します。

{
  "Comment": "A description of my state machine",
  "StartAt": "Lambda Invoke",
  "States": {
    "Lambda Invoke": {
      "Type": "Task",
      "Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken",
      "Parameters": {
        "Payload": {
          "token.$": "$$.Task.Token"
        },
        "FunctionName": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:FunctionName:$LATEST"
      },
      "Retry": [
        {
          "ErrorEquals": [
            "Lambda.ServiceException",
            "Lambda.AWSLambdaException",
            "Lambda.SdkClientException",
            "Lambda.TooManyRequestsException"
          ],
          "IntervalSeconds": 1,
          "MaxAttempts": 3,
          "BackoffRate": 2
        }
      ],
      "Next": "Wait"
    },
    "Wait": {
      "Type": "Wait",
      "End": true,
      "TimestampPath": "$.expirydate"
    }
  }
}

グラフビューで見ると以下のようになります。

スクリーンショット 2024-08-06 15.20.37

早速実行しましょう!

Lambda からステートマシンへ返却された結果は以下になります。

{
  "output": {
    "expirydate": "2024-08-06T06:05:33Z"
  },
  "outputDetails": {
    "truncated": false
  },
  "resource": "invoke.waitForTaskToken",
  "resourceType": "lambda"
}

Wait 状態への入力結果はこちらです。

{
  "input": {
    "expirydate": "2024-08-06T06:05:33Z"
  },
  "inputDetails": {
    "truncated": false
  },
  "name": "Wait"
}

Wait 状態は以下のように 2024年8月6日 15:05:34.013 (UTC+09:00) に終了しています。
上記時間を ISO8601 形式に変換すると 2024-08-06T06:05:34.013Z となり、おおよそ入力の時間で終了していることがわかります。

スクリーンショット 2024-08-06 15.24.55

上記結果より、Wait 状態で前状態から入力された時間まで待機させることが可能なことが確認できました。

参考資料

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.