Step FunctionsのResultSelectorを使って次のtaskへ変数を渡す

やったこと

  • Step Functionsで少々複雑なStateMachineを作ってしまい
  • StateMachineのtaskを跨いだ変数の受け渡しについて調査していたら、なかなか時間がかかったのでここに残しておきます
  • ResultSelectorを使って解決できました
  • CloudFormation(yaml)での設定例を載せています

先にまとめ

  • ResultSelectorを使うとそのtask実行後のoutputから任意の値を取り出して(filterして)、ResultPathに設定したpahtに出力される
  • Inputするjsonの内容を補正するための設定値
  • yamlでのCloudFormationではこんな感じで書く
run-task-A:
  Type: Task
  ...
  ResultSelector:
    Args.$: $.Arguments
  ...

ResultSelector設定時の挙動

例) このtaskrun-task-Aでは一つ前のtaskから受け取った値$.test_option_beforeをtask内で使用するためArgumentsに渡しています

          ...
          run-task-A:
            Type: Task
            Resource: arn:aws:states:::glue:startJobRun.sync
            Parameters:
              JobName: !Ref ExtractionGlueJob
              Arguments:
                test_option_after.$: $.test_option_before
            ResultSelector:
              Args.$: $.Arguments
            ResultPath: $
          run-task-B:
            Type: Task
            Resource: arn:aws:states:::glue:startJobRun.sync
            Parameters:
              Arguments:
                test_option_after.$: $.Args.test_option_after
            ...

上記の場合はkey:ArgsArgumentsの中身を出力され下記の結果が出力される

{
  "Args": {
    "test_option": "test_value"
  }
}

もしResultSelectorの設定が無い場合、Parameters.ArgumentsのArguments部分がkeyとなって下記のようになる

{
  "Arguments": {
    "test_option": "test_value"
  }
}

こんな感じのことをしてくれる設定値のようで、使う場面なんて限られてるので深くまで動きを把握していませんでしたが、今回ついに使う場面が登場しました

役に立ったケース

choice taskで中間のtaskをskipするパターンがあり、ResultPathを固定して後続のtaskでも同じ記述(Path?key?)で値を呼び出したい
具体的には下記のようなstatemachine

test_optionの値を呼び出す場合、
TaskBをskipすると$.Args.test_optionで呼び出せるが、TaskBをskipしない場合は別のpath(TaskBの出力内容に依存)になっているケースがあるため$.Args.test_optionでは呼び出せない
TaskCでtest_optionの値を使用したいけど、$.Args.test_option or$.???.test_optionの状態になってしまいTaskCの設定が両パターンに対応できない

これを補正するためにResultSelectorResultPathを使って、output(json)の指定の位置へ期待する値を出力させることができました

結論

ResultSelectorResultPathは名前のままの動きをしてくれる
…けど…色々複雑になるから…できれば使いたくない