こんにちは、CX事業本部 IoT事業部の若槻です。
今日もいつものようにAWS Step Fucntionsのドキュメントやソースコードを見ていたところ、EvaluateExpressionなるものを見つけました。
内容を見てみると、なんと任意のJavaScript表現を実行できるタスクのようです...!!!
そこで今回は、EvaluateExpressionタスクを使って文字列置換を行うステートマシンを実装してみました。
やってみた
実装
AWS CDK v2(TypeScript)で次のようなCDKスタックを作成します。
lib/process-stack.ts
import { Construct } from 'constructs';
import {
aws_stepfunctions,
aws_stepfunctions_tasks,
Stack,
StackProps,
} from 'aws-cdk-lib';
export class ProcessStack extends Stack {
constructor(scope: Construct, id: string, props: StackProps) {
super(scope, id, props);
//JSONPathを使わない場合
const evaluateTask1 = new aws_stepfunctions_tasks.EvaluateExpression(
this,
'evaluateTask1',
{
expression: '"インスタンスメソッド".replace("インスタンス", "クラス")',
resultPath: '$.evaluateTask1',
},
);
//JSONPathを使う場合
const evaluateTask2 = new aws_stepfunctions_tasks.EvaluateExpression(
this,
'evaluateTask2',
{
expression: aws_stepfunctions.JsonPath.format(
'"{}".replace("{}", "{}")',
aws_stepfunctions.JsonPath.stringAt('$.original'),
aws_stepfunctions.JsonPath.stringAt('$.substr'),
aws_stepfunctions.JsonPath.stringAt('$.newSubstr'),
),
resultPath: '$.evaluateTask2',
},
);
// ステートマシン
new aws_stepfunctions.StateMachine(this, 'stateMachine', {
stateMachineName: 'stateMachine',
definition: evaluateTask1.next(evaluateTask2),
});
}
}
EvaluateExpression()
のexpression
で、実行したいJavaScript表現を指定します。States.Format
を使用してInputの値を指定すること可能です。
上記をCDK Deployしてスタックをデプロイします。これにより次のDefinitionのステートマシンが作成されます。種明かしなのですがEvaluateExpression()
はLambda関数リソース(Node.jsランタイム)が隠蔽されたHigh Level Constructです。
Definition
{
"StartAt": "evaluateTask1",
"States": {
"evaluateTask1": {
"Next": "evaluateTask2",
"Type": "Task",
"ResultPath": "$.evaluateTask1",
"Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:ProcessStack-Evalda2d1181604e4a4586941a6abd7fe42dF-oEnIyas250LB",
"Parameters": {
"expression": "\"インスタンスメソッド\".replace(\"インスタンス\", \"クラス\")",
"expressionAttributeValues": {}
}
},
"evaluateTask2": {
"End": true,
"Type": "Task",
"ResultPath": "$.evaluateTask2",
"Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:ProcessStack-Evalda2d1181604e4a4586941a6abd7fe42dF-oEnIyas250LB",
"Parameters": {
"expression.$": "States.Format('\"{}\".replace(\"{}\", \"{}\")', $.original, $.substr, $.newSubstr)",
"expressionAttributeValues": {}
}
}
}
}
作成されたLambda関数のコードを見ると、引数のexpression
をeval()
してReturnしていることが分かります。
Lambda Function
'use strict';
Object.defineProperty(exports, '__esModule', { value: !0 }),
(exports.handler = void 0);
function escapeRegex(x) {
return x.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
async function handler(event) {
console.log('Event: %j', event);
const expression = Object.entries(event.expressionAttributeValues).reduce(
(exp, [k, v]) =>
exp.replace(new RegExp(escapeRegex(k), 'g'), JSON.stringify(v)),
event.expression
);
return console.log(`Expression: ${expression}`), eval(expression);
}
exports.handler = handler;
//# sourceMappingURL=index.js.map
動作確認
次の入力を指定してステートマシンを実行します。
{
"original": "オールドモード",
"substr": "オールド",
"newSubstr": "ネクスト"
}
実行が成功しました。
evaluateTask1
では、文字列置換によりクラスメソッド
が取得できています!
evaluateTask1
では、JSONPathの入力を元にした文字列置換によりネクストモード
が取得できています!
おわりに
任意のJavaScript表現を実行できるEvaluateExpressionタスクを使って文字列置換をしてみました。
ある程度の処理のタスクであれば最小限のコードの記述だけで作成できてしまうなんて凄すぎますね。今回やった文字列置換の他にも四則演算や日付処理などeval()
に渡せるものなら何でも出来てしまいます。
ローコードツールとしてのAWS Step Functionsの可能性を大幅に拡張する機能だと思うので、今後はどんどん利用し、またどんどん周知していきたいと思います。
参考
以上