AWS Step Functionsの新しい組み込み関数がAWS CDKの専用クラスで実装できるようになっていました
こんにちは、CX事業本部 IoT事業部の若槻です。
AWS Step Functionsの大型アップデートとして、今年の8月に14個の新しい組み込み関数(Intrinsic functions)が追加されました。
組み込み関数を使うと配列操作やJsonオブジェクト操作などのデータ処理を追加のTask(AWS Lambdaなど)を呼び出すことなく行えるのですが、この時のアップデートにより、より多くの操作が組み込み関数を使用して行えるようになり、Step Functionsの実装をより簡潔化できるようになりました。
しかし残念ながら、当時は、まだそれらの新しい組み込み関数を実装できるAWS CDKの専用クラスは提供されていなかったため、CDKで新しい組み込み関数を実装したい場合は"States.MathAdd(6, 4)"
のように関数をベタ書きで記述する必要がありました。
しかし本日改めて確認してみると、新しい組み込み関数の専用クラスがCDKでも利用可能となっていたので、試してみました。
やってみた
CDK Construct Libraryのアップグレード
リリース履歴を追ってみると、CDK Construct Libraryで削除保護の設定がサポートされたのは本記事の執筆日の25日前にリリースされたv2.50.0
からでした。
stepfunctions: add intrinsic functions (#22431) (8f85b08), closes #22068 #22629
必要に応じてライブラリをアップグレードします。
npm i aws-cdk-lib@latest aws-cdk@latest constructs@latest
私の環境の場合は前回のエントリで別の新機能を使えるようにするために既に2.51.0
アップグレード済みでした。
実装
新しい組み込み関数を含む、現在使える18個すべての組み込み関数の実装を試してみます。(ちなみに下記表および検証方法は、のんぴのエントリを参考しました)
組み込み関数 | 説明 |
---|---|
States.Array | 配列を返す |
States.ArrayPartition | 配列を分割する |
States.ArrayContains | 特定の値が配列に存在するかどうか返す |
States.ArrayRange | 特定の範囲の要素を含む配列を作成する |
States.ArrayGetItem | 配列の指定されたインデックスの値を返す |
States.ArrayLength | 配列の長さを返す |
States.ArrayUnique | 配列から重複する値を削除して一意の要素のみを含む配列を返す |
States.Base64Encode | MIME Base64でをエンコードする |
States.Base64Decode | MIME Base64でデコードする |
States.Hash | ハッシュ値を計算する |
States.JsonMerge | 2つのJSONオブジェクトを1つのオブジェクトにマージする |
States.StringToJson | エスケープされたJSON文字列からJSONオブジェクトを返す |
States.JsonToString | JSONオブジェクトからエスケープされたJSON文字列を返す |
States.MathRandom | 指定された開始番号と終了番号の間の乱数を返す |
States.MathAdd | 2つの数値の合計を返す |
States.StringSplit | 文字列を配列に分割する |
States.UUID | UUID v4を返す |
States.Format | テンプレートリテラルと補完値から文字列を返す |
CDK Stackの実装です。aws_stepfunctions.JsonPath
に含まれる組み込み関数の専用クラスを使用しています。
import { aws_stepfunctions, Stack, StackProps } from 'aws-cdk-lib'; import { Construct } from 'constructs'; export class AwsCdkAppStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); const intrinsicFunctionsPass = new aws_stepfunctions.Pass( this, 'intrinsicFunctionsPass', { parameters: { StatesArray: aws_stepfunctions.JsonPath.array( aws_stepfunctions.JsonPath.stringAt('$.json1'), aws_stepfunctions.JsonPath.stringAt('$.json2') ), StatesArrayPartition: aws_stepfunctions.JsonPath.arrayPartition( aws_stepfunctions.JsonPath.listAt('$.inputArray'), 2 ), StatesArrayContains: aws_stepfunctions.JsonPath.arrayContains( aws_stepfunctions.JsonPath.listAt('$.inputArray'), 'd' ), StatesArrayRange: aws_stepfunctions.JsonPath.arrayRange(0, 1000, 333), StatesArrayGetItem: aws_stepfunctions.JsonPath.arrayGetItem( aws_stepfunctions.JsonPath.listAt('$.inputArray'), 3 ), StatesArrayLength: aws_stepfunctions.JsonPath.arrayLength( aws_stepfunctions.JsonPath.listAt('$.inputArray') ), StatesArrayUnique: aws_stepfunctions.JsonPath.arrayUnique( aws_stepfunctions.JsonPath.listAt('$.inputArray') ), StatesBase64Encode: aws_stepfunctions.JsonPath.base64Encode( aws_stepfunctions.JsonPath.stringAt('$.inputText') ), StatesBase64Decode: aws_stepfunctions.JsonPath.base64Decode( aws_stepfunctions.JsonPath.stringAt('$.inputBase64') ), StatesHash: aws_stepfunctions.JsonPath.hash( aws_stepfunctions.JsonPath.stringAt('$.inputText'), 'SHA-512' ), StatesJsonMerge: aws_stepfunctions.JsonPath.jsonMerge( aws_stepfunctions.JsonPath.stringAt('$.json1'), aws_stepfunctions.JsonPath.stringAt('$.json2') ), StatesStringToJson: aws_stepfunctions.JsonPath.stringToJson('{"foo": "bar"}'), StatesJsonToString: aws_stepfunctions.JsonPath.jsonToString( aws_stepfunctions.JsonPath.stringAt('$.json1') ), StatesMathRandom: aws_stepfunctions.JsonPath.mathRandom(0, 10000), StatesMathAdd: aws_stepfunctions.JsonPath.mathAdd(200, 12), StatesStringSplit: aws_stepfunctions.JsonPath.stringSplit( aws_stepfunctions.JsonPath.stringAt('$.inputText'), 'me' ), StatesUUID: aws_stepfunctions.JsonPath.uuid(), StatesFormat: aws_stepfunctions.JsonPath.format( 'Hello, this is {}.', aws_stepfunctions.JsonPath.stringAt('$.inputText') ), }, } ); new aws_stepfunctions.StateMachine(this, 'myStateMachine', { stateMachineName: 'myStateMachine', definition: intrinsicFunctionsPass, }); } }
CDK Deployし、次のInputを指定してState Machineを実行します。
{ "inputArray": [ "a", "a", "b", "c", "c", "c", "d", "e", "e", "f", "g" ], "inputText": "classmethod", "inputBase64": "44Kv44Op44K544Oh44K944OD44OJ", "json1": { "a": { "a1": 1, "a2": 2 }, "b": 2 }, "json2": { "a": { "a3": 1, "a4": 2 }, "c": 3 } }
実行が成功しました。
ちゃんと期待通りのOutputを得ることができました。
{ "StatesStringSplit": [ "class", "thod" ], "StatesArrayPartition": [ [ "a", "a" ], [ "b", "c" ], [ "c", "c" ], [ "d", "e" ], [ "e", "f" ], [ "g" ] ], "StatesBase64Encode": "Y2xhc3NtZXRob2Q=", "StatesArray": [ { "a": { "a1": 1, "a2": 2 }, "b": 2 }, { "a": { "a3": 1, "a4": 2 }, "c": 3 } ], "StatesJsonMerge": { "a": { "a3": 1, "a4": 2 }, "b": 2, "c": 3 }, "StatesFormat": "Hello, this is classmethod.", "StatesJsonToString": "{\"a\":{\"a1\":1,\"a2\":2},\"b\":2}", "StatesBase64Decode": "クラスメソッド", "StatesUUID": "2eb7bd4d-0009-4c0e-89cc-6833f218d78e", "StatesMathRandom": 7801, "StatesArrayUnique": [ "a", "b", "c", "d", "e", "f", "g" ], "StatesHash": "79943e30c9f79c2051dfb2716135498646546321cfd8b77ef683db35b787a8a604db11dc722c7d3100fcb9b08c42cfa5ba7167db2ccf18d36725d1ba6c6fc757", "StatesArrayRange": [ 0, 333, 666, 999 ], "StatesArrayContains": true, "StatesArrayGetItem": "c", "StatesStringToJson": { "foo": "bar" }, "StatesArrayLength": 11, "StatesMathAdd": 212 }
注意点
ドキュメントによると、States.MathRandom
では3つ目の引数でシード値をオプションで取ります。
引数1(開始番号)、引数2(終了番号)および引数3(シード値)で同じ値が指定される限り、States.MathRandom
は同じ値を返すようになります。
しかしCDKのクラス実装では3つ目の引数であるシード値の指定はサポートされていないようです。
もしCDKでシード値を指定したい場合はクラスを使わずに"States.MathRandom(0, 10000, 3)"
のように関数をベタ書きするようにしましょう。
おわりに
AWS Step Functionsの新しい組み込み関数がAWS CDKの専用クラスで実装できるようになっていたので試してみました。
今までも関数ベタ書きにより使えなくは無かったのですが、クラスを使うことができればTypeScriptの型補完を効かせつつ実装できるので開発が便利になります。嬉しいですね。
以上