Lambdaのイベントソースマッピングでフィルタ設定ができるようになっています。
今回は、特定のAttributeが追加、または、削除されたときだけ起動するように、イベントソースマッピングのフィルタ設定をしてみました。
おすすめの方
- AWS SAMでLambdaのイベントソースマッピングのフィルタ設定をしたい方
- DynamoDBで特定のAttributeが追加、または、削除されたときだけLambdaを起動するフィルタ設定をしたい方
- AWS CLIでDynamoDBテーブルにデータを追加・更新したい方
DynamoDB StreamsとLambdaをデプロイする
sam init
sam init \
--runtime python3.9 \
--name DynamoDB-Streams-Lambda-Filter-Sample \
--app-template hello-world \
--no-tracing \
--package-type Zip
AWS SAMテンプレート
今回は、特定のAttribute(memo
)が追加、または、削除されたときにLambdaを起動するフィルターを設定してみます。
ただし、INSERTおよびREMOVE時は、Lambdaを起動させないようにします。
簡単にまとめると下記です。
- INSERT
- Lambdaを起動しない
- MODIFY
memo
が追加されたら、Lambdaを起動するmemo
が削除されたら、Lambdaを起動する
- REMOVE
- Lambdaを起動しない
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: DynamoDB-Streams-Lambda-Filter-Sample
Resources:
DeviceSampleTable:
DeletionPolicy: Retain
UpdateReplacePolicy: Retain
Type: AWS::DynamoDB::Table
Properties:
TableName: device-sample-table
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: deviceId
AttributeType: S
KeySchema:
- AttributeName: deviceId
KeyType: HASH
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.9
Timeout: 3
Architectures:
- x86_64
Events:
DeviceSampleTableStream:
Type: DynamoDB
Properties:
BatchSize: 100
BisectBatchOnFunctionError: true
FilterCriteria:
Filters:
- Pattern: '{"eventName":["MODIFY"],"dynamodb":{"NewImage":{"memo":{"S":[{"exists":true}]}},"OldImage":{"memo":{"S":[{"exists":false}]}}}}'
- Pattern: '{"eventName":["MODIFY"],"dynamodb":{"NewImage":{"memo":{"S":[{"exists":false}]}},"OldImage":{"memo":{"S":[{"exists":true}]}}}}'
MaximumRetryAttempts: 3
StartingPosition: TRIM_HORIZON
Stream: !GetAtt DeviceSampleTable.StreamArn
HelloWorldFunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${HelloWorldFunction}
フィルタ設定を見やすくすると下記です。
{
"eventName": [
"MODIFY"
],
"dynamodb": {
"NewImage": {
"memo": {
"S": [{"exists": true}]
}
},
"OldImage": {
"memo": {
"S": [{"exists": false}]
}
}
}
}
{
"eventName": [
"MODIFY"
],
"dynamodb": {
"NewImage": {
"memo": {
"S": [{"exists": false}]
}
},
"OldImage": {
"memo": {
"S": [{"exists": true}]
}
}
}
}
なお、exists
を次のように設定すると駄目でした。DynamoDBの型情報(S
などの部分)が必要です。ご注意ください。
{
"eventName": [
"MODIFY"
],
"dynamodb": {
"NewImage": {
"memo": [{"exists": false}]
},
"OldImage": {
"memo": [{"exists": true}]
}
}
}
Lambdaコード
ログ出力するだけです。
app.py
import json
def lambda_handler(event, context):
for record in event['Records']:
print(json.dumps(record))
デプロイ
sam deploy \
--stack-name DynamoDB-Streams-Lambda-Filter-Sample-Stack \
--s3-bucket cm-fujii.genki-deploy \
--capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
動作確認をする
INSERT
memoがあるデータを追加します。フィルタ条件を満たしていないので、Lambdaは起動しないはずです。
aws dynamodb put-item \
--table-name device-sample-table \
--item '{"deviceId":{"S":"device1"}, "name": {"S":"class"}, "memo": {"S": "public"}}'
REMOVE
さきほど追加したmemoがあるデータを削除します。フィルタ条件を満たしていないので、Lambdaは起動しないはずです。
aws dynamodb delete-item \
--table-name device-sample-table \
--key '{"deviceId":{"S":"device1"}}'
MODIFY
memoが無いデータを追加します。フィルタ条件を満たしていないので、Lambdaは起動しないはずです。
aws dynamodb put-item \
--table-name device-sample-table \
--item '{"deviceId":{"S":"device1"}, "name": {"S":"class"}}'
新しいAttribute(memo)を追加します。フィルタ条件を満たすので、Lambdaは起動するはずです。
aws dynamodb update-item \
--table-name device-sample-table \
--key '{"deviceId":{"S":"device1"}}' \
--update-expression 'SET #memo=:memo' \
--expression-attribute-names '{"#memo":"memo"}' \
--expression-attribute-values '{":memo":{"S":"This is memo!"}}'
次に、memoを変更します。フィルタ条件を満たしていないので、Lambdaは起動しないはずです。
aws dynamodb update-item \
--table-name device-sample-table \
--key '{"deviceId":{"S":"device1"}}' \
--update-expression 'SET #memo=:memo' \
--expression-attribute-names '{"#memo":"memo"}' \
--expression-attribute-values '{":memo":{"S":"This is memo??????"}}'
memoを削除します。フィルタ条件を満たすので、Lambdaは起動するはずです。
aws dynamodb update-item \
--table-name device-sample-table \
--key '{"deviceId":{"S":"device1"}}' \
--update-expression 'REMOVE #memo' \
--expression-attribute-names '{"#memo":"memo"}'
CloudWatch Logsを見る
Lambdaの起動は、2回です。
それぞれのログを見ると、memo
が新しく追加されたデータ、および、memo
が無くなったデータでした。期待通りですね。
さいごに
フィルタ設定をするとき、S
などの型情報も必要です。お忘れなく……。