AWS Step FunctionsステートマシンでDynamoDBテーブルからアイテムを取得してMapステートで処理する

2021.11.02

こんにちは、CX事業本部 IoT事業部の若槻です。

今回は、AWS Step FunctionsステートマシンでDynamoDBテーブルからアイテムを取得してMapステートで処理してみました。

作るもの

指定のエリアにいるクルーに次に移動するべきエリアを通知するアプリです。

やってみた

対象のDynamoDBテーブル

下記のクルーの現在位置と従業員情報を管理するDynamoDBテーブルをクエリ対象とします。

  • テーブル名:crews
  • PK:crewId(String)
  • GSI名:areaId-index
  • GSI-PK:areaId(String)

格納されているデータは以下となります。

ステートマシンの作成

Step Functions Workflow Studioでステートマシンを作成します。

Step Functionsのマネジメントコンソールでステートマシンの作成を開始します。

[次へ]をクリックします。

[action]をqueryで検索して[DynamoDB Query]をドラッグします。

[Query]の[設定]で、[APIパラメータ]で下記のJSONを指定します。

{
  "TableName": "crews",
  "IndexName": "areaId-index",
  "ExpressionAttributeNames": {
    "#areaId": "areaId"
  },
  "ExpressionAttributeValues": {
    ":areaId": {
      "S.$": "$.areaId"
    }
  },
  "KeyConditionExpression": "#areaId = :areaId"
}

[Query]の[出力]で、[ResultSelector]と[ResultPath]を指定します。

  • ResultSelector
{
  "Items.$": "$.Items"
}
  • ResultPath
$.crews

[フロー]から[Query]の下の位置へ[Map]をドラッグして追加します。

Mapの[設定]-[項目配列へのパス]で$.crews.Itemsを指定します。

同じくMapの[入力]-[配列項目を変換]で以下のJSONを指定します。

{
  "phoneNumber.$": "$$.Map.Item.Value.phoneNumber.S",
  "message.$": "$.message",
  "senderId.$": "$.senderId"
}

[アクション]から[Amazon SNS]のPublishMapの中にドラッグして追加します。

SNS Publishの[設定]で[Integration type]をAWS SDKに変更し、[APIパラメータ]に以下のJSONを指定します。

{
  "PhoneNumber.$": "$.phoneNumber",
  "Message.$": "$.message",
  "MessageAttributes": {
    "AWS.SNS.SMS.SenderID": {
      "DataType": "String",
      "StringValue.$": "$.senderId"
    }
  }
}

その後、[次へ]をクリックします。

生成されたコードを確認したら[次へ]をクリックします。

今回生成されたコード(ステートマシン定義)は下記のようになります。

{
  "Comment": "A description of my state machine",
  "StartAt": "Query",
  "States": {
    "Query": {
      "Type": "Task",
      "Parameters": {
        "TableName": "crews",
        "IndexName": "areaId-index",
        "ExpressionAttributeNames": {
          "#areaId": "areaId"
        },
        "ExpressionAttributeValues": {
          ":areaId": {
            "S.$": "$.areaId"
          }
        },
        "KeyConditionExpression": "#areaId = :areaId"
      },
      "Resource": "arn:aws:states:::aws-sdk:dynamodb:query",
      "ResultSelector": {
        "Items.$": "$.Items"
      },
      "ResultPath": "$.crews",
      "Next": "Map"
    },
    "Map": {
      "Type": "Map",
      "End": true,
      "Iterator": {
        "StartAt": "SNS Publish",
        "States": {
          "SNS Publish": {
            "Type": "Task",
            "Resource": "arn:aws:states:::aws-sdk:sns:publish",
            "Parameters": {
              "PhoneNumber.$": "$.phoneNumber",
              "Message.$": "$.message",
              "MessageAttributes": {
                "AWS.SNS.SMS.SenderID": {
                  "DataType": "String",
                  "StringValue.$": "$.senderId"
                }
              }
            },
            "End": true
          }
        }
      },
      "ItemsPath": "$.crews.Items",
      "Parameters": {
        "phoneNumber.$": "$$.Map.Item.Value.phoneNumber.S",
        "message.$": "$.message",
        "senderId.$": "$.senderId"
      }
    }
  }
}

[ステートマシンの作成]をクリックして作成を完了します。

ステートマシンを作成できました。不足しているDynamoDBへのアクセス権限を付与するために[IAMでロールを編集]をクリックします。

今回はAWS管理ポリシーのAmazonDynamoDBReadOnlyAccessをアタッチしました。(ポリシーは必要に応じて用意してください)

動作

Step Functionsのコンソールに戻り、入力で下記のようなJSONを指定して、ステートマシンを実行します。a001のエリアにいるクルーにTaito-Kuに移動するように通知する入力です。

{
  "areaId": "a001",
  "message": "Please move to Taito-Ku.",
  "senderId": "AllocateApp"
}

実行が成功しました。

それぞれのクルーの電話番号の端末でもSMSのメッセージが受信できています。

参考

以上