はじめに
AWSのEventBridgeを使用して定期実行などを行う際、最低1回の実行が保証されている(参照)。
しかし、処理によっては多重実行が望まれないものもある。
そこで今回は、DynamoDBを用いて、stepfunctionsの多重実行を制御する方法を考えた。
実装
今回は、日次で1回のみ行う処理をイメージした。ステートマシンの構造は以下の通りである。
- DynamoDBに実行日を表す値(yyyymmdd)を入れる
- 上の処理が正常に動作したらメインの処理が走る、エラーが起こったらステートマシンを終了する
DynamoDBのテーブル作成
今回はtestというテーブル名で、パーティションキーをyyyymmddとするテーブルを作成した。
ステートマシンの作成
以下のようなイメージのステートマシンを作成した。
なお、今回は、多重実行が制御できれば良いので、メインの処理はmainという名のpassステートで代用してある。
{
"Comment": "A description of my state machine",
"StartAt": "PutItem",
"States": {
"PutItem": {
"Type": "Task",
"Resource": "arn:aws:states:::dynamodb:putItem",
"Parameters": {
"TableName": "test",
"ConditionExpression": "attribute_not_exists(yyyymmdd)",
"Item": {
"yyyymmdd": {
"S.$": "$.yyyymmdd"
}
}
},
"ResultPath": null,
"Catch": [
{
"ErrorEquals": [
"DynamoDB.ConditionalCheckFailedException"
],
"Next": "Already put"
}
],
"Next": "main"
},
"Already put": {
"Type": "Pass",
"End": true
},
"main": {
"Type": "Pass",
"End": true
}
}
}
パラメータ説明
putItem
Request Parameterに関するドキュメント
- "parameters"内の"ConditionExpression"を"attribute_not_exsits(yyyymmdd)"とすることで、指定したyyyymmddが既に存在しているかどうかを判定する(参照)。
- 既にDynamoDBに値が存在している場合、"DynamoDB.ConditionalCheckFailedException"が返却されるので、これを"Catch"で受け取っている。
動作検証
DynamoDBに値が入っていない場合
実行結果
期待通り、ステートマシン上ではPutItemの次にmain処理を走らせることに成功した。
ちなみにこのとき、以下のようにDynamoDBに20220101の値が入っていることが確認できる。
DynamoDBに既に値が入っている場合
上の状態から、再度同じ条件でステートマシンを実行した。
実行結果
期待通り、PutItemで起こったERRORをCatchし、main処理が走ることなく、Already putステートに処理が移った。
まとめ
今回実装したPutItemステートを多重実行制御したいステートマシンに入れることにより、簡単に多重実行制御ができることがわかった。実行ログの記録としての役割も同時にDynamoDBは果たすことができるので、DynamoDBに入れる値も工夫の余地があると考えられる。