AWS Step Functionsで組み込み関数だけで配列の作成を行う方法2通り(AWS CDK v2)
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、AWS Step Functionsで組み込み関数だけで配列の作成を行うステートマシンをAWS CDK v2(TypeScript)で実装してみました。
方法
以下の2通りの方法が確認できたのでそれぞれ紹介します。
aws_stepfunctions.JsonPath.array
aws_stepfunctions_tasks.DynamoAttributeValue.fromList
方法1:aws_stepfunctions.JsonPath.array
次のようなCDKスタックを作成します。
import { Construct } from 'constructs'; import { aws_stepfunctions, Stack, StackProps } from 'aws-cdk-lib'; export class ProcessStack extends Stack { constructor(scope: Construct, id: string, props: StackProps) { super(scope, id, props); // 配列の作成 const createArrayTask = new aws_stepfunctions.Pass( this, 'createArrayTask', { parameters: { array: aws_stepfunctions.JsonPath.array( 'あああ', aws_stepfunctions.JsonPath.stringAt('$.val1'), aws_stepfunctions.JsonPath.stringAt('$.val2'), ), }, resultPath: '$.createArrayTaskOutPut', }, ); // ステートマシン new aws_stepfunctions.StateMachine(this, 'stateMachine', { stateMachineName: 'stateMachine', definition: createArrayTask, }); } }
- 使用しているのは組み込み関数(Itrinsic functions)の
States.Array
です。 - AWS CDKではItrinsic functionsについても
JsonPath
上でMethodが用意されています。
上記をCDK Deployしてスタックをデプロイします。これにより次のDefinitionのステートマシンが作成されます。
{ "StartAt": "createArrayTask", "States": { "createArrayTask": { "Type": "Pass", "ResultPath": "$.createArrayTaskOutPut", "Parameters": { "array.$": "States.Array('あああ', $.val1, $.val2)" }, "End": true } } }
次の入力を指定してステートマシンを実行します。
{ "val1": "candy", "val2": "choco" }
すると実行が成功しました。
createArrayTask
で、JSONPathから取得した値を使用して配列が作成できています。
方法2:aws_stepfunctions_tasks.DynamoAttributeValue.fromList
次のようなCDKスタックを作成します。
import { Construct } from 'constructs'; import { aws_stepfunctions, aws_stepfunctions_tasks, aws_dynamodb, Stack, StackProps, RemovalPolicy, } from 'aws-cdk-lib'; export class ProcessStack extends Stack { constructor(scope: Construct, id: string, props: StackProps) { super(scope, id, props); // 適当なDynamoDBテーブル const someTable = new aws_dynamodb.Table(this, 'someTable', { tableName: 'someTable', partitionKey: { name: 'id', type: aws_dynamodb.AttributeType.STRING, }, billingMode: aws_dynamodb.BillingMode.PAY_PER_REQUEST, removalPolicy: RemovalPolicy.DESTROY, }); // 配列の作成 const createArrayTask = new aws_stepfunctions.Pass( this, 'createArrayTask', { parameters: { array: aws_stepfunctions_tasks.DynamoAttributeValue.fromList([ aws_stepfunctions_tasks.DynamoAttributeValue.fromString( aws_stepfunctions.JsonPath.stringAt('$.val1'), ), aws_stepfunctions_tasks.DynamoAttributeValue.fromString( aws_stepfunctions.JsonPath.stringAt('$.val2'), ), ]), }, resultPath: '$.createArrayTaskOutPut', }, ); // 配列への要素追加 const appendToArrayTask = new aws_stepfunctions_tasks.DynamoUpdateItem( this, 'appendToArrayTask', { table: someTable, key: { id: aws_stepfunctions_tasks.DynamoAttributeValue.fromString('aaaaaa'), //適当なキー値 }, expressionAttributeNames: { '#array': 'array', }, expressionAttributeValues: { //要素追加先の配列として利用 ':target': aws_stepfunctions_tasks.DynamoAttributeValue.listFromJsonPath( aws_stepfunctions.JsonPath.stringAt( '$.createArrayTaskOutPut.array.attributeValue.L', ), ), ':appends': aws_stepfunctions_tasks.DynamoAttributeValue.fromList([ aws_stepfunctions_tasks.DynamoAttributeValue.fromString( aws_stepfunctions.JsonPath.stringAt('$.val3'), ), ]), }, updateExpression: 'SET #array = list_append(:target, :appends)', returnValues: aws_stepfunctions_tasks.DynamoReturnValues.UPDATED_NEW, resultSelector: { items: aws_stepfunctions.JsonPath.stringAt( '$.Attributes.array.L[*].S', ), }, resultPath: '$.appendToArrayTask.OutPut', }, ); // 通常の配列に変換する場合 const convertToUsualArray = new aws_stepfunctions.Pass( this, 'convertToUsualArray', { parameters: { usualArray: aws_stepfunctions.JsonPath.stringAt( '$.createArrayTaskOutPut.array.attributeValue.L[*].S', ), }, }, ); // ステートマシン new aws_stepfunctions.StateMachine(this, 'stateMachine', { stateMachineName: 'stateMachine', definition: createArrayTask .next(appendToArrayTask) .next(convertToUsualArray), }); } }
- 使用しているのはDynamoAttributeValue ClassのfromList Methodです。
- 正確に言うとStep Functionsの組み込み関数ではありませんね。
- これによりDynamoAttributeValue型の配列を作成します。
- DynamoAttributeValue型なのでステートマシン内の後続処理でDynamoDBへの処理に利用する際に便利です。
- またJsonPathを上手く使用すれば通常の配列に簡単に変換できます。
上記をCDK Deployしてスタックをデプロイします。これにより次のDefinitionのステートマシンが作成されます。
{ "StartAt": "createArrayTask", "States": { "createArrayTask": { "Type": "Pass", "ResultPath": "$.createArrayTaskOutPut", "Parameters": { "array": { "attributeValue": { "L": [ { "S.$": "$.val1" }, { "S.$": "$.val2" } ] } } }, "Next": "appendToArrayTask" }, "appendToArrayTask": { "Next": "convertToUsualArray", "Type": "Task", "ResultPath": "$.appendToArrayTask.OutPut", "ResultSelector": { "items.$": "$.Attributes.array.L" }, "Resource": "arn:aws:states:::dynamodb:updateItem", "Parameters": { "Key": { "id": { "S": "aaaaaa" } }, "TableName": "someTable", "ExpressionAttributeNames": { "#array": "array" }, "ExpressionAttributeValues": { ":target": { "L.$": "$.createArrayTaskOutPut.array.attributeValue.L" }, ":appends": { "L": [ { "S.$": "$.val3" } ] } }, "ReturnValues": "UPDATED_NEW", "UpdateExpression": "SET #array = list_append(:target, :appends)" } }, "convertToUsualArray": { "Type": "Pass", "Parameters": { "usualArray.$": "$.createArrayTaskOutPut.array.attributeValue.L[*].S" }, "End": true } } }
次の入力を指定してステートマシンを実行します。
{ "val1": "candy", "val2": "choco", "val3": "cacao" }
すると実行が成功しました。
createArrayTask
では、JSONPathから取得した値を使用してAttributeValue
形式の配列が取得できています。
"appendToArrayTask": { "OutPut": { "items": [ { "S": "candy" }, { "S": "choco" }, { "S": "cacao" } ] } }
appendToArrayTask
では、createArrayTask
で作成した配列に要素を追加できています。
"appendToArrayTask": { "OutPut": { "items": [ { "S": "candy" }, { "S": "choco" }, { "S": "cacao" } ] } }
convertToUsualArray
では、createArrayTask
で作成したAttributeValue
形式の配列を通常の形式に変換できています。
"usualArray": [ "candy", "choco" ]
おわりに
AWS Step Functionsで組み込み関数だけで配列の作成を行うステートマシンをAWS CDK v2(TypeScript)で実装してみました。
Itrinsic functionsのCDKの組み込みのClassが今までもあるだろうなと思いつつ探しきれていなかったので、今回方法が確認できて良かったです。
参考
- AWS Step FunctionsステートマシンでLambdaを使わずに配列の作成や要素追加を行うアイデア(AWS CDK v2) | DevelopersIO
- AWS Step Functionsでは組み込み関数だけで配列のフィルターやスライスができる(AWS CDK v2) | DevelopersIO
以上