翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
での DynamoDB トランザクションの実行 AWS AppSync
AWS AppSync は、1 つのリージョン内の 1 つ以上のテーブルで Amazon DynamoDB トランザクションオペレーションの使用をサポートします。サポートされている処理は、TransactGetItems
および TransactWriteItems
です。でこれらの機能を使用すると AWS AppSync、次のようなタスクを実行できます。
-
単一クエリでキーのリストを渡し、テーブルからの結果を返す
-
単一クエリで 1 つ以上のテーブルからレコードを読み取る
-
トランザクションのレコードを all-or-nothing1 つ以上のテーブルに何らかの方法で書き込む
-
一部の条件が満たされたときにトランザクションを実行します
アクセス許可
他のリゾルバーと同様に、 でデータソースを作成し AWS AppSync 、ロールを作成するか、既存のものを使用する必要があります。トランザクションオペレーションでは DynamoDB テーブルごとに異なるアクセス許可が必要であるため、読み取りまたは書き込みアクションのために設定されたアクセス許可がロールに必要です。
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:UpdateItem" ], "Effect": "Allow", "Resource": [ "arn:aws:dynamodb:region:accountId:table/TABLENAME", "arn:aws:dynamodb:region:accountId:table/TABLENAME/*" ] } ] }
注記
ロールは のデータソースに関連付けられ AWS AppSync、フィールドのリゾルバーはデータソースに対して呼び出されます。DynamoDB に対して取得するよう設定されたデータソースは、設定を単純にするために 1 つのテーブルのみ指定されます。したがって、単一のリゾルバーで複数のテーブルに対してトランザクションオペレーションを実行する場合、これはより高度なタスクであり、リゾルバーが利用するすべてのテーブルへのアクセスをデータソースのロールに許可する必要があります。これは、上記のIAMポリシーのリソースフィールドで行われます。テーブルに対するトランザクション呼び出しの設定は、リゾルバーのテンプレートで行います。これについては以下で説明します。
データソース
分かりやすくするために、このチュートリアルではすべてのリゾルバーに同じデータソースを使用します。
savingAccounts と という 2 つのテーブルがありcheckingAccounts、どちらもパーティションキーaccountNumber
として 、パーティションキーtransactionId
として というtransactionHistoryテーブルがあります。次のCLIコマンドを使用してテーブルを作成できます。必ずリージョンを region
に置き換えてください。
で CLI
aws dynamodb create-table --table-name savingAccounts \ --attribute-definitions AttributeName=accountNumber,AttributeType=S \ --key-schema AttributeName=accountNumber,KeyType=HASH \ --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \ --table-class STANDARD --region region aws dynamodb create-table --table-name checkingAccounts \ --attribute-definitions AttributeName=accountNumber,AttributeType=S \ --key-schema AttributeName=accountNumber,KeyType=HASH \ --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \ --table-class STANDARD --region region aws dynamodb create-table --table-name transactionHistory \ --attribute-definitions AttributeName=transactionId,AttributeType=S \ --key-schema AttributeName=transactionId,KeyType=HASH \ --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \ --table-class STANDARD --region region
AWS AppSync コンソールのデータソース で、新しい DynamoDB データソースを作成し、名前を付けますTransactTutorial。テーブルsavingAccountsとして を選択します (トランザクションを使用する場合、特定のテーブルは関係ありません)。[新規] を選択して、新しいロールとデータソースを作成します。データソースの設定を確認して、生成されたロールの名前を確認できます。IAM コンソールで、データソースがすべてのテーブルと対話できるようにするインラインポリシーを追加できます。
region
および accountID
をお客様のリージョンとアカウント ID に置き換えます。
{ "Version": "2012-10-17", "Statement": [ { "Action": [ "dynamodb:DeleteItem", "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:UpdateItem" ], "Effect": "Allow", "Resource": [ "arn:aws:dynamodb:region:accountId:table/savingAccounts", "arn:aws:dynamodb:region:accountId:table/savingAccounts/*", "arn:aws:dynamodb:region:accountId:table/checkingAccounts", "arn:aws:dynamodb:region:accountId:table/checkingAccounts/*", "arn:aws:dynamodb:region:accountId:table/transactionHistory", "arn:aws:dynamodb:region:accountId:table/transactionHistory/*" ] } ] }
トランザクション
この例では、コンテキストは従来の銀行取引で、次の目的で TransactWriteItems
を使用します。
-
普通預金から当座預金への振替
-
取引ごとの新しい取引レコードの生成
次に、TransactGetItems
を使用して、普通預金と当座預金の詳細を取得します。
警告
TransactWriteItems
は、競合の検出と解決とともに使用する場合はサポートされていません。これらの設定は、起こり得るエラーを防ぐために無効にする必要があります。
次のように GraphQL スキーマを定義します。
type SavingAccount { accountNumber: String! username: String balance: Float } type CheckingAccount { accountNumber: String! username: String balance: Float } type TransactionHistory { transactionId: ID! from: String to: String amount: Float } type TransactionResult { savingAccounts: [SavingAccount] checkingAccounts: [CheckingAccount] transactionHistory: [TransactionHistory] } input SavingAccountInput { accountNumber: String! username: String balance: Float } input CheckingAccountInput { accountNumber: String! username: String balance: Float } input TransactionInput { savingAccountNumber: String! checkingAccountNumber: String! amount: Float! } type Query { getAccounts(savingAccountNumbers: [String], checkingAccountNumbers: [String]): TransactionResult } type Mutation { populateAccounts(savingAccounts: [SavingAccountInput], checkingAccounts: [CheckingAccountInput]): TransactionResult transferMoney(transactions: [TransactionInput]): TransactionResult }
TransactWriteItems - アカウントを入力する
口座間で振替を行うには、テーブルに詳細を入力する必要があります。これを実行するには、GraphQL オペレーション Mutation.populateAccounts
を使用します。
[スキーマ] セクションで、Mutation.populateAccounts
オペレーションの横にある [アタッチ] をクリックします。TransactTutorial
データソースを選択し、[作成] を選択します。
ここで、以下のコードを使用します。
import { util } from '@aws-appsync/utils' export function request(ctx) { const { savingAccounts, checkingAccounts } = ctx.args const savings = savingAccounts.map(({ accountNumber, ...rest }) => { return { table: 'savingAccounts', operation: 'PutItem', key: util.dynamodb.toMapValues({ accountNumber }), attributeValues: util.dynamodb.toMapValues(rest), } }) const checkings = checkingAccounts.map(({ accountNumber, ...rest }) => { return { table: 'checkingAccounts', operation: 'PutItem', key: util.dynamodb.toMapValues({ accountNumber }), attributeValues: util.dynamodb.toMapValues(rest), } }) return { version: '2018-05-29', operation: 'TransactWriteItems', transactItems: [...savings, ...checkings], } } export function response(ctx) { if (ctx.error) { util.error(ctx.error.message, ctx.error.type, null, ctx.result.cancellationReasons) } const { savingAccounts: sInput, checkingAccounts: cInput } = ctx.args const keys = ctx.result.keys const savingAccounts = sInput.map((_, i) => keys[i]) const sLength = sInput.length const checkingAccounts = cInput.map((_, i) => keys[sLength + i]) return { savingAccounts, checkingAccounts } }
リゾルバーを保存し、 AWS AppSync コンソールのクエリセクションに移動してアカウントを入力します。
次のミューテーションを実行します。
mutation populateAccounts { populateAccounts ( savingAccounts: [ {accountNumber: "1", username: "Tom", balance: 100}, {accountNumber: "2", username: "Amy", balance: 90}, {accountNumber: "3", username: "Lily", balance: 80}, ] checkingAccounts: [ {accountNumber: "1", username: "Tom", balance: 70}, {accountNumber: "2", username: "Amy", balance: 60}, {accountNumber: "3", username: "Lily", balance: 50}, ]) { savingAccounts { accountNumber } checkingAccounts { accountNumber } } }
1 つのミューテーションで 3 つの普通預金口座と 3 つの当座預金口座に入力しました。
DynamoDB コンソールを使用して、データが savingAccountsと checkingAccounts テーブルの両方に表示されることを確認します。
TransactWriteItems - 送金
次のコードを使用して transferMoney
ミューテーションにリゾルバーをアタッチします。送金ごとに、当座預金口座と普通預金口座の両方に成功修飾子が必要で、取引中の送金を追跡する必要があります。
import { util } from '@aws-appsync/utils' export function request(ctx) { const transactions = ctx.args.transactions const savings = [] const checkings = [] const history = [] transactions.forEach((t) => { const { savingAccountNumber, checkingAccountNumber, amount } = t savings.push({ table: 'savingAccounts', operation: 'UpdateItem', key: util.dynamodb.toMapValues({ accountNumber: savingAccountNumber }), update: { expression: 'SET balance = balance - :amount', expressionValues: util.dynamodb.toMapValues({ ':amount': amount }), }, }) checkings.push({ table: 'checkingAccounts', operation: 'UpdateItem', key: util.dynamodb.toMapValues({ accountNumber: checkingAccountNumber }), update: { expression: 'SET balance = balance + :amount', expressionValues: util.dynamodb.toMapValues({ ':amount': amount }), }, }) history.push({ table: 'transactionHistory', operation: 'PutItem', key: util.dynamodb.toMapValues({ transactionId: util.autoId() }), attributeValues: util.dynamodb.toMapValues({ from: savingAccountNumber, to: checkingAccountNumber, amount, }), }) }) return { version: '2018-05-29', operation: 'TransactWriteItems', transactItems: [...savings, ...checkings, ...history], } } export function response(ctx) { if (ctx.error) { util.error(ctx.error.message, ctx.error.type, null, ctx.result.cancellationReasons) } const tInput = ctx.args.transactions const tLength = tInput.length const keys = ctx.result.keys const savingAccounts = tInput.map((_, i) => keys[tLength * 0 + i]) const checkingAccounts = tInput.map((_, i) => keys[tLength * 1 + i]) const transactionHistory = tInput.map((_, i) => keys[tLength * 2 + i]) return { savingAccounts, checkingAccounts, transactionHistory } }
次に、 AWS AppSync コンソールのクエリセクションに移動し、次のようにtransferMoneyミューテーションを実行します。
mutation write { transferMoney( transactions: [ {savingAccountNumber: "1", checkingAccountNumber: "1", amount: 7.5}, {savingAccountNumber: "2", checkingAccountNumber: "2", amount: 6.0}, {savingAccountNumber: "3", checkingAccountNumber: "3", amount: 3.3} ]) { savingAccounts { accountNumber } checkingAccounts { accountNumber } transactionHistory { transactionId } } }
1 つのミューテーションで 2 つの銀行取引を送信しました。DynamoDB コンソールを使用して、データが savingAccounts、、checkingAccountsおよび transactionHistoryテーブルに表示されることを確認します。
TransactGetItems - アカウントを取得する
1 つの取引リクエストで普通預金口座と当座預金口座から詳細を取得するために、スキーマで Query.getAccounts
GraphQL オペレーションにリゾルバーをアタッチします。[アタッチ] を選択し、次の画面で、このチュートリアルの最初で作成したのと同じ TransactTutorial
データソースを選択します。以下のコードを使用します。
import { util } from '@aws-appsync/utils' export function request(ctx) { const { savingAccountNumbers, checkingAccountNumbers } = ctx.args const savings = savingAccountNumbers.map((accountNumber) => { return { table: 'savingAccounts', key: util.dynamodb.toMapValues({ accountNumber }) } }) const checkings = checkingAccountNumbers.map((accountNumber) => { return { table: 'checkingAccounts', key: util.dynamodb.toMapValues({ accountNumber }) } }) return { version: '2018-05-29', operation: 'TransactGetItems', transactItems: [...savings, ...checkings], } } export function response(ctx) { if (ctx.error) { util.error(ctx.error.message, ctx.error.type, null, ctx.result.cancellationReasons) } const { savingAccountNumbers: sInput, checkingAccountNumbers: cInput } = ctx.args const items = ctx.result.items const savingAccounts = sInput.map((_, i) => items[i]) const sLength = sInput.length const checkingAccounts = cInput.map((_, i) => items[sLength + i]) return { savingAccounts, checkingAccounts } }
リゾルバーを保存し、 AWS AppSync コンソールのクエリセクションに移動します。普通預金口座と当座預金口座を取得するには、次のクエリを実行します。
query getAccounts { getAccounts( savingAccountNumbers: ["1", "2", "3"], checkingAccountNumbers: ["1", "2"] ) { savingAccounts { accountNumber username balance } checkingAccounts { accountNumber username balance } } }
を使用した DynamoDB トランザクションの使用を正常に実証しました AWS AppSync。