はじめに
この記事は NTTテクノクロスAdvent Calendar 2022 の 4日目の記事です。
NTTテクノクロスの井上です。
普段はAWS関連の業務をしています。
この記事では、
AppSyncでDynamoDBのトランザクション処理をおこなう方法についてご紹介します。
目次
構成
作成するアーキテクチャはこのような図になります。
DynamoDBの2つのテーブルに、同時にデータを書き込む処理を作ります。
DynamoDB
この記事で扱うテーブルの定義はこちらの通りです。
- FooTable
カラム名 | 型 | |
---|---|---|
ID | String | パーティションキー |
foo | String | - |
- BarTable
カラム名 | 型 | |
---|---|---|
ID | String | パーティションキー |
bar | String | - |
IAM
AppSyncにDynamoDBの権限を付与するためにロールを作成します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:DeleteItem",
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:UpdateItem"
],
"Resource": [
"arn:aws:dynamodb:ap-northeast-1:<アカウントID>:table/FooTable",
"arn:aws:dynamodb:ap-northeast-1:<アカウントID>:table/FooTable/*",
"arn:aws:dynamodb:ap-northeast-1:<アカウントID>:table/BarTable",
"arn:aws:dynamodb:ap-northeast-1:<アカウントID>:table/BarTable/*"
]
}
]
}
AppSync
データソース
データソースを作成します。
テーブル名は、トランザクションオペレーションのリクエストマッピングテンプレートで指定するので、何でも構いません。
項目 | 設定値 |
---|---|
データソース名 | FooTable |
データソースタイプ | Amazon DynamoDB テーブル |
リージョン | AP-NORTHEAST-1 |
テーブル名 | FooTable |
既存のロールを作成または使用する | 先ほど作成したIAMロールを選択 |
スキーマ
スキーマを作成します。
この例では、次のことをおこなうためにTransactWriteItems
を使用します。
- FooTableにfooデータを登録・更新
- BarTableにbarデータを登録・更新
type Bar {
id: String!
bar: String
}
input BarInput {
id: String!
bar: String
}
type Foo {
id: String!
foo: String
}
input FooInput {
id: String!
foo: String
}
type Mutation {
transactTests(Bar: [BarInput], Foo: [FooInput]): TransactionResult
}
type Query {
getFoo(id: String!): Foo
getBar(id: String!): Bar
}
type TransactionResult {
foo: [Foo]
bar: [Bar]
}
schema {
query: Query
mutation: Mutation
}
リゾルバー
transactTests
のリゾルバーを作成します。
データソースには先ほど作成したFooTable
を選択します。
リクエストマッピングテンプレート
#set($BarTransactPutItems = [])
#set($index = 0)
#foreach($Bar in ${ctx.args.Bar})
#set($keyMap = {})
$util.qr($keyMap.put("id", $util.dynamodb.toString($Bar.id)))
#set($attributeValues = {})
$util.qr($attributeValues.put("bar", $util.dynamodb.toString($Bar.bar)))
#set($index = $index + 1)
#set($BarTransactPutItem = {"table": "BarTable",
"operation": "PutItem",
"key": $keyMap,
"attributeValues": $attributeValues})
$util.qr($BarTransactPutItems.add($BarTransactPutItem))
#end
#set($FooTransactPutItems = [])
#set($index = 0)
#foreach($Foo in ${ctx.args.Foo})
#set($keyMap = {})
$util.qr($keyMap.put("id", $util.dynamodb.toString($Foo.id)))
#set($attributeValues = {})
$util.qr($attributeValues.put("foo", $util.dynamodb.toString($Foo.foo)))
#set($index = $index + 1)
#set($FooTransactPutItem = {"table": "FooTable",
"operation": "PutItem",
"key": $keyMap,
"attributeValues": $attributeValues})
$util.qr($FooTransactPutItems.add($FooTransactPutItem))
#end
#set($transactItems = [])
$util.qr($transactItems.addAll($BarTransactPutItems))
$util.qr($transactItems.addAll($FooTransactPutItems))
{
"version" : "2018-05-29",
"operation" : "TransactWriteItems",
"transactItems" : $util.toJson($transactItems)
}
レスポンスマッピングテンプレート
#if ($ctx.error)
$util.appendError($ctx.error.message, $ctx.error.type, null, $ctx.result.cancellationReasons)
#end
#set($bar = [])
$util.qr($bar.add(${ctx.result.keys[0]}))
#set($foo = [])
$util.qr($foo.add(${ctx.result.keys[1]}))
#set($transactionResult = {})
$util.qr($transactionResult.put('bar', $bar))
$util.qr($transactionResult.put('foo', $foo))
$util.toJson($transactionResult)
実行
実際にクエリを打って正しく動くか試してみます。
2つのテーブルに正しく登録されたことを確認できました。
おわりに
今回は、AppSyncでDynamoDBのトランザクション処理をおこなう方法をご紹介しました。
少しでも参考にしていただけたら嬉しいです。
では、NTTテクノクロスAdvent Calendar 2022 の 5日目も、お楽しみください!