🔥

[AWS] StepFunctionsのMAP内でDynamoDB updateItemを動かそうとしたらドハマりした話

2024/12/05に公開

前提条件

  • Json形式のデータに含まれるキーと値のリストをDynamoDBに入力する。
  • StepFunctionsの機能のみで実現する。

発生した問題

最初の構築

ステートマシン
MAPとUpdateItemだけのシンプルなステートマシンをGUIで作成する。
キーと値はid/samplevalueとするため、この状態で定義ファイルは以下のようになる。

{
  "QueryLanguage": "JSONata",
  "Comment": "A description of my state machine",
  "StartAt": "Map",
  "States": {
    "Map": {
      "Type": "Map",
      "ItemProcessor": {
        "ProcessorConfig": {
          "Mode": "INLINE"
        },
        "StartAt": "DynamoDB UpdateItem",
        "States": {
          "DynamoDB UpdateItem": {
            "Type": "Task",
            "Resource": "arn:aws:states:::dynamodb:updateItem",
            "Arguments": {
              "TableName": "MyDynamoDBTable",
              "Key": {
                "id": {
                  "S": "$.id"
                }
              },
              "UpdateExpression": "SET samplevalue = :myValueRef",
              "ExpressionAttributeValues": {
                ":myValueRef": {
                  "S": "$.samplevalue"
                }
              }
            },
            "End": true
          }
        }
      },
      "End": true
    }
  }
}

問題

自動生成だからこれで動くだろうと思ったら、変数の中身が反映されず次のようなレコードが追加されてしまった。

id samplevalue
$.id $.samplevalue

これに関しては、"S"を、"S.$"に変更するといいよとChatGPTやQが教えてくれるのだが、その変更をすると今度は次のように怒られる。

The field "S.$" is not supported by Step Functions. Did you mean 'SS'? /States/Map/ItemProcessor/States/DynamoDB UpdateItem/Arguments

さらにいろいろ調べていくと、ArgumentsではなくParametersを使うパターンが見つかったので書き換えてみるが、今度は次のエラーが出た。

ワークフローに 3 件のエラーが見つかりました。 このページにとどまり、エラーを修正しますか?
DynamoDB UpdateItem (Arguments.TableName): Value is mandatory.
DynamoDB UpdateItem (Arguments.Key): Value is mandatory.
DynamoDB UpdateItem (Parameters): Field is not available.

AIの言うとおりに修正を試すが複数のパターンをループするだけで一向に解決しなかった。

解決

ArgumentsとParametersの違い

これはQueryLanguageがJSONataかJSONPathかによって異なる。JSONataの方が高機能だが、MAPではJSONPathが推奨されるらしい。
今回はデフォルトでJSONataが選択されていたため、Parametersが使えず、その中で変数を指定する方法も従来のものが使えなかった、ということになる。

一番簡単なのは、最初にステートマシンクエリ言語でJSONPathを選ぶことでした。

最終的な記載

{
  "QueryLanguage": "JSONPath",
  "Comment": "A description of my state machine",
  "StartAt": "Map",
  "States": {
    "Map": {
      "Type": "Map",
      "ItemProcessor": {
        "ProcessorConfig": {
          "Mode": "INLINE"
        },
        "StartAt": "DynamoDB UpdateItem",
        "States": {
          "DynamoDB UpdateItem": {
            "Type": "Task",
            "Resource": "arn:aws:states:::dynamodb:updateItem",
            "Parameters": {
              "TableName": "Stables",
              "Key": {
                "id": {
                  "S.$": "$$.Map.Item.id"
                }
              },
              "UpdateExpression": "SET samplevalue = :myValueRef",
              "ExpressionAttributeValues": {
                ":myValueRef": {
                  "S.$": "$$.Map.Item.samplevalue"
                }
              }
            },
            "End": true
          }
        }
      },
      "End": true
    }
  }
}

QueryLanguageを変更することでS.$が使えるようになるため、無事文字列型でidを指定することができるようになったため、変数の書き込みが可能になった。
※実際に使用した環境とは列名などを変えているため、このまま動作するかはわかりません。

Discussion