AWS Step Functionsの変数とJSONataで一定回数のループを実現する

AWS Step Functionsの変数とJSONataで一定回数のループを実現する

変数とJSONataを使うことで、Step Functionsだけで非常に簡単に一定回数のループを実現できました。
Clock Icon2025.02.12

データ事業本部の鈴木です。

テストなどでAWSのサービスに対して同じ処理の繰り返しを行いたいことがあり、AWS Step Functionsを使った実装を試したいなと考えていたのですが、少し前に変数とJSONataのサポートがされたお知らせがあったのを思い出したので、この機能を使った実装を検証しました。

ステートマシンで一定回数のループを実現するには

ステートマシンで一定回数のループを実現するのは、実はこれまでは工夫が必要でした。同期実行をサポートしていないAPIを利用する場合などでは、例えば以下の記事のように、ステートマシン内でAPI呼び出しを行った後、APIで実行した機能の終了ステータスを別途取得し、その値を見てループを抜けるというような実装が一般的です。

https://dev.classmethod.jp/articles/statemachine-import-data-dataset-amazon-forecast/

一方で、一定回数でループを抜けるためには、例えば以下のガイドのようにLambdaでインクリメントを行っていくというような、擬似的に先のループの仕組みを作るような工夫が必要でした。

https://docs.aws.amazon.com/ja_jp/step-functions/latest/dg/tutorial-create-iterate-pattern-section.html

そのほかには加算でLambdaを使わないように以下のような工夫をしたりもしていました。

https://dev.classmethod.jp/articles/ideas-to-addsubtract-numbers-without-lambda-in-aws-step-functions-state-machines-aws-cdk-v2/

先日のアップデートでStep Functionsが変数とJSONataをサポートしたことにより、変数に値を保持することに加え、その変数をステートマシン内でインクリメントすることができるようになりました。これにより様々な実装がStep Functionsのみで完結するようになりましたが、今回もその機能を利用しています。

変数とJSONataについては以下の資料を見て頂くと分かりやすいです。

実装例の紹介

全体像とコード

Step Functions Workflow Studioで以下のステートマシンを作成しました。QueryLanguageとして新しく利用できるようになったJSONataを使っています。loop_cnt変数をループ内でインクリメントして、30を超えるとループを抜けて終了します。

作成したステートマシン

{
  "QueryLanguage": "JSONata",
  "Comment": "A description of my state machine",
  "StartAt": "Init",
  "States": {
    "Init": {
      "Type": "Pass",
      "Assign": {
        "loop_cnt": 0
      },
      "Next": "Add"
    },
    "Add": {
      "Type": "Pass",
      "Assign": {
        "loop_cnt": "{% $loop_cnt + 1 %}"
      },
      "Next": "Choice"
    },
    "Choice": {
      "Type": "Choice",
      "Choices": [
        {
          "Next": "Add",
          "Condition": "{% $loop_cnt <= 29 %}"
        }
      ],
      "Default": "Pass"
    },
    "Pass": {
      "Type": "Pass",
      "End": true,
      "Output": {
        "loop_cnt": "{% $loop_cnt %}"
      }
    }
  }
}

ループを抜ける判定は今回はChoiceに不等式でハードコードしていますが、ここも変数やパラメータにするとより汎用性が広がりそうです。(無限ループにだけ気をつけましょう!)

上記だけだとただループするだけのステートマシンになるので、別途ループ内にサービスを利用するためのステートを追加するイメージです。

実行例

Initステートでloop_cnt変数を初期化し、ループを開始します。

ステートマシンの開始

最終的にloop_cntは30になって終了しました。

ステートマシンの終了

ポイント

変数初期値の設定

初期値はpassステートで設定しました。

    "Init": {
      "Type": "Pass",
      "Assign": {
        "loop_cnt": 0
      },
      "Next": "Add"
    },

変数のインクリメント

JSONataを使うことで、変数に対して値の更新ができるため、インクリメントするようにしました。

    "Add": {
      "Type": "Pass",
      "Assign": {
        "loop_cnt": "{% $loop_cnt + 1 %}"
      },
      "Next": "Choice"
    },

Choiceでの変数評価

こちらもJSONataを使っています。

以下のガイドから、変数xの参照は$xというように行えることが読み取れたので、Choiceのルールで評価しました。

https://docs.aws.amazon.com/step-functions/latest/dg/workflow-variables.html

    "Choice": {
      "Type": "Choice",
      "Choices": [
        {
          "Next": "Add",
          "Condition": "{% $loop_cnt <= 29 %}"
        }
      ],
      "Default": "Pass"
    },

最後に

変数とJSONataを使うことで、Step Functionsだけで非常に簡単に一定回数のループを実現できました。
参考になりましたら幸いです。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.