Tutorial: Durchführen von DynamoDB-Transaktionen in AWS AppSync - AWS AppSync

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

Tutorial: Durchführen von DynamoDB-Transaktionen in AWS AppSync

Anmerkung

Wir unterstützen jetzt hauptsächlich die APPSYNC _JS-Laufzeit und ihre Dokumentation. Bitte erwägen Sie, die APPSYNC _JS-Laufzeit und ihre Anleitungen hier zu verwenden.

AWS AppSync unterstützt die Verwendung von Amazon DynamoDB-Transaktionsoperationen für eine oder mehrere Tabellen in einer einzigen Region. Zu den unterstützten Operationen gehören TransactGetItems und TransactWriteItems. Mithilfe dieser Funktionen können Sie Aufgaben wie die folgenden ausführen: AWS AppSync

  • Übermitteln einer Liste von Schlüsseln in einer einzigen Abfrage und Zurückgabe der Ergebnisse aus einer Tabelle

  • Lesen der Datensätze aus einer oder mehrerer Tabellen in einer einzigen Abfrage

  • Schreiben Sie Datensätze in einer Transaktion auf irgendeine all-or-nothing Weise in eine oder mehrere Tabellen

  • Ausführen von Transaktionen, wenn einige Bedingungen erfüllt sind

Berechtigungen

Wie bei anderen Resolvern müssen Sie eine Datenquelle in erstellen AWS AppSync und entweder eine Rolle erstellen oder eine vorhandene verwenden. Da Transaktionsvorgänge unterschiedliche Berechtigungen für DynamoDB-Tabellen erfordern, müssen Sie den konfigurierten Rollen Berechtigungen für Lese- oder Schreibaktionen gewähren:

{ "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/*" ] } ] }

Hinweis: Rollen sind an Datenquellen in einer Datenquelle gebunden AWS AppSync, und Resolver für Felder werden für eine Datenquelle aufgerufen. Für Datenquellen, die für den Abruf von DynamoDB konfiguriert sind, ist nur eine Tabelle angegeben, um die Konfiguration zu vereinfachen. Möchten Sie jedoch einen Transaktionsvorgang an mehreren Tabellen mit nur einem Resolver ausführen, stellt dies eine erweiterte Aufgabe dar, und Sie müssen der Rolle dieser Datenquelle Zugriff auf alle Tabellen gewähren, mit denen der Resolver interagieren wird. Dies würde in der obigen Richtlinie im Feld Ressource geschehen. IAM Die Konfiguration der Tabellen, um Transaktionsaufrufe auszuführen, erfolgt in der Resolver-Vorlage und wird nachfolgend beschrieben.

Datenquelle

Der Einfachheit halber verwenden wir die gleiche Datenquelle für alle in diesem Tutorial verwendeten Resolver. Erstellen Sie auf der Registerkarte Datenquellen eine neue DynamoDB-Datenquelle und geben Sie ihr einen Namen. TransactTutorial Sie können den Namen der Tabelle frei wählen, da Tabellennamen als Teil der Zuweisungsvorlage für Anforderungen bei Transaktionsvorgängen angegeben werden. Wir geben der Tabelle den Namen empty.

Wir werden zwei Tabellen mit dem Namen savingAccountsund haben checkingAccounts, beide mit accountNumber als Partitionsschlüssel und eine transactionHistoryTabelle mit transactionId als Partitionsschlüssel.

Für dieses Tutorial kann jede Rolle mit der folgenden eingebundenen Richtlinie verwendet werden: Ersetze region und accountId durch deine Region und Konto-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/*" ] } ] }

Transaktionen

Für dieses Beispiel ist der Kontext eine klassische Banktransaktion, bei der wir TransactWriteItems für folgende Aktionen verwenden:

  • Überweisen von Geld von Sparkonten auf Girokonten

  • Generieren neuer Transaktionsdatensätze für jede Transaktion

Anschließend verwenden wir TransactGetItems, um Details der Sparkonten und Girokonten abzurufen.

Warnung

TransactWriteItemswird nicht unterstützt, wenn es zusammen mit Konflikterkennung und Konfliktlösung verwendet wird. Diese Einstellungen müssen deaktiviert werden, um mögliche Fehler zu vermeiden.

Wir definieren unser GraphQL-Schema wie folgt:

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 } schema { query: Query mutation: Mutation }

TransactWriteItems - Konten auffüllen

Um Geld zwischen Konten zu übertragen, müssen wir die Tabelle mit den Details füllen. Wir verwenden dazu die GraphQL-Operation Mutation.populateAccounts.

Klicken Sie im Abschnitt Schema neben dem Mutation.populateAccounts Vorgang auf Anhängen. Gehen Sie zu VTL Unit Resolvers und wählen Sie dann dieselbe TransactTutorial Datenquelle aus.

Verwenden Sie die folgende Zuweisungsvorlage für Anforderungen:

Zuweisungsvorlage für Anforderungen

#set($savingAccountTransactPutItems = []) #set($index = 0) #foreach($savingAccount in ${ctx.args.savingAccounts}) #set($keyMap = {}) $util.qr($keyMap.put("accountNumber", $util.dynamodb.toString($savingAccount.accountNumber))) #set($attributeValues = {}) $util.qr($attributeValues.put("username", $util.dynamodb.toString($savingAccount.username))) $util.qr($attributeValues.put("balance", $util.dynamodb.toNumber($savingAccount.balance))) #set($index = $index + 1) #set($savingAccountTransactPutItem = {"table": "savingAccounts", "operation": "PutItem", "key": $keyMap, "attributeValues": $attributeValues}) $util.qr($savingAccountTransactPutItems.add($savingAccountTransactPutItem)) #end #set($checkingAccountTransactPutItems = []) #set($index = 0) #foreach($checkingAccount in ${ctx.args.checkingAccounts}) #set($keyMap = {}) $util.qr($keyMap.put("accountNumber", $util.dynamodb.toString($checkingAccount.accountNumber))) #set($attributeValues = {}) $util.qr($attributeValues.put("username", $util.dynamodb.toString($checkingAccount.username))) $util.qr($attributeValues.put("balance", $util.dynamodb.toNumber($checkingAccount.balance))) #set($index = $index + 1) #set($checkingAccountTransactPutItem = {"table": "checkingAccounts", "operation": "PutItem", "key": $keyMap, "attributeValues": $attributeValues}) $util.qr($checkingAccountTransactPutItems.add($checkingAccountTransactPutItem)) #end #set($transactItems = []) $util.qr($transactItems.addAll($savingAccountTransactPutItems)) $util.qr($transactItems.addAll($checkingAccountTransactPutItems)) { "version" : "2018-05-29", "operation" : "TransactWriteItems", "transactItems" : $util.toJson($transactItems) }

Und die folgende Zuweisungsvorlage für Antworten:

Zuweisungsvorlage für Antworten

#if ($ctx.error) $util.appendError($ctx.error.message, $ctx.error.type, null, $ctx.result.cancellationReasons) #end #set($savingAccounts = []) #foreach($index in [0..2]) $util.qr($savingAccounts.add(${ctx.result.keys[$index]})) #end #set($checkingAccounts = []) #foreach($index in [3..5]) $util.qr($checkingAccounts.add(${ctx.result.keys[$index]})) #end #set($transactionResult = {}) $util.qr($transactionResult.put('savingAccounts', $savingAccounts)) $util.qr($transactionResult.put('checkingAccounts', $checkingAccounts)) $util.toJson($transactionResult)

Speichern Sie den Resolver und navigieren Sie zum Abschnitt Abfragen der AWS AppSync Konsole, um die Konten aufzufüllen.

Führen Sie die folgende Mutation aus:

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 } } }

Wir haben drei Sparkonten und drei Girokonten in einer Mutation gefüllt.

Verwenden Sie die DynamoDB-Konsole, um zu überprüfen, ob Daten sowohl in der als auch in der savingAccountsTabelle angezeigt werden. checkingAccounts

TransactWriteItems - Geld überweisen

Fügen Sie der transferMoney-Mutation mithilfe der folgenden Zuweisungsvorlage für Anforderungen einen Resolver an. Beachten Sie, dass die Werte von amounts, savingAccountNumbers und checkingAccountNumbers identisch sind.

#set($amounts = []) #foreach($transaction in ${ctx.args.transactions}) #set($attributeValueMap = {}) $util.qr($attributeValueMap.put(":amount", $util.dynamodb.toNumber($transaction.amount))) $util.qr($amounts.add($attributeValueMap)) #end #set($savingAccountTransactUpdateItems = []) #set($index = 0) #foreach($transaction in ${ctx.args.transactions}) #set($keyMap = {}) $util.qr($keyMap.put("accountNumber", $util.dynamodb.toString($transaction.savingAccountNumber))) #set($update = {}) $util.qr($update.put("expression", "SET balance = balance - :amount")) $util.qr($update.put("expressionValues", $amounts[$index])) #set($index = $index + 1) #set($savingAccountTransactUpdateItem = {"table": "savingAccounts", "operation": "UpdateItem", "key": $keyMap, "update": $update}) $util.qr($savingAccountTransactUpdateItems.add($savingAccountTransactUpdateItem)) #end #set($checkingAccountTransactUpdateItems = []) #set($index = 0) #foreach($transaction in ${ctx.args.transactions}) #set($keyMap = {}) $util.qr($keyMap.put("accountNumber", $util.dynamodb.toString($transaction.checkingAccountNumber))) #set($update = {}) $util.qr($update.put("expression", "SET balance = balance + :amount")) $util.qr($update.put("expressionValues", $amounts[$index])) #set($index = $index + 1) #set($checkingAccountTransactUpdateItem = {"table": "checkingAccounts", "operation": "UpdateItem", "key": $keyMap, "update": $update}) $util.qr($checkingAccountTransactUpdateItems.add($checkingAccountTransactUpdateItem)) #end #set($transactionHistoryTransactPutItems = []) #foreach($transaction in ${ctx.args.transactions}) #set($keyMap = {}) $util.qr($keyMap.put("transactionId", $util.dynamodb.toString(${utils.autoId()}))) #set($attributeValues = {}) $util.qr($attributeValues.put("from", $util.dynamodb.toString($transaction.savingAccountNumber))) $util.qr($attributeValues.put("to", $util.dynamodb.toString($transaction.checkingAccountNumber))) $util.qr($attributeValues.put("amount", $util.dynamodb.toNumber($transaction.amount))) #set($transactionHistoryTransactPutItem = {"table": "transactionHistory", "operation": "PutItem", "key": $keyMap, "attributeValues": $attributeValues}) $util.qr($transactionHistoryTransactPutItems.add($transactionHistoryTransactPutItem)) #end #set($transactItems = []) $util.qr($transactItems.addAll($savingAccountTransactUpdateItems)) $util.qr($transactItems.addAll($checkingAccountTransactUpdateItems)) $util.qr($transactItems.addAll($transactionHistoryTransactPutItems)) { "version" : "2018-05-29", "operation" : "TransactWriteItems", "transactItems" : $util.toJson($transactItems) }

Wir werden drei Banktransaktionen in einem einzigen TransactWriteItems-Vorgang durchführen. Verwenden Sie die folgende Vorlage für die Zuordnung von Antworten:

#if ($ctx.error) $util.appendError($ctx.error.message, $ctx.error.type, null, $ctx.result.cancellationReasons) #end #set($savingAccounts = []) #foreach($index in [0..2]) $util.qr($savingAccounts.add(${ctx.result.keys[$index]})) #end #set($checkingAccounts = []) #foreach($index in [3..5]) $util.qr($checkingAccounts.add(${ctx.result.keys[$index]})) #end #set($transactionHistory = []) #foreach($index in [6..8]) $util.qr($transactionHistory.add(${ctx.result.keys[$index]})) #end #set($transactionResult = {}) $util.qr($transactionResult.put('savingAccounts', $savingAccounts)) $util.qr($transactionResult.put('checkingAccounts', $checkingAccounts)) $util.qr($transactionResult.put('transactionHistory', $transactionHistory)) $util.toJson($transactionResult)

Navigieren Sie nun zum Abschnitt Abfragen der AWS AppSync Konsole und führen Sie die transferMoneyMutation wie folgt aus:

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 } } }

Wir haben zwei Banktransaktionen in einer Mutation gesendet. Verwenden Sie die DynamoDB-Konsole, um zu überprüfen, ob Daten in den Tabellen savingAccountscheckingAccounts, und transactionHistoryangezeigt werden.

TransactGetItems - Konten abrufen

Um die Details aus dem Sparkonto und dem Girokonto in einer einzigen Transaktionsanforderung abzurufen, hängen wir einen Resolver an die Query.getAccounts-GraphQL-Operation in unserem Schema an. Wählen Sie Anhängen, gehen Sie zu VTL Unit Resolvers und wählen Sie dann auf dem nächsten Bildschirm dieselbe TransactTutorial Datenquelle aus, die zu Beginn des Tutorials erstellt wurde. Konfigurieren Sie die Vorlagen wie folgt:

Zuweisungsvorlage für Anforderungen

#set($savingAccountsTransactGets = []) #foreach($savingAccountNumber in ${ctx.args.savingAccountNumbers}) #set($savingAccountKey = {}) $util.qr($savingAccountKey.put("accountNumber", $util.dynamodb.toString($savingAccountNumber))) #set($savingAccountTransactGet = {"table": "savingAccounts", "key": $savingAccountKey}) $util.qr($savingAccountsTransactGets.add($savingAccountTransactGet)) #end #set($checkingAccountsTransactGets = []) #foreach($checkingAccountNumber in ${ctx.args.checkingAccountNumbers}) #set($checkingAccountKey = {}) $util.qr($checkingAccountKey.put("accountNumber", $util.dynamodb.toString($checkingAccountNumber))) #set($checkingAccountTransactGet = {"table": "checkingAccounts", "key": $checkingAccountKey}) $util.qr($checkingAccountsTransactGets.add($checkingAccountTransactGet)) #end #set($transactItems = []) $util.qr($transactItems.addAll($savingAccountsTransactGets)) $util.qr($transactItems.addAll($checkingAccountsTransactGets)) { "version" : "2018-05-29", "operation" : "TransactGetItems", "transactItems" : $util.toJson($transactItems) }

Zuweisungsvorlage für Antworten

#if ($ctx.error) $util.appendError($ctx.error.message, $ctx.error.type, null, $ctx.result.cancellationReasons) #end #set($savingAccounts = []) #foreach($index in [0..2]) $util.qr($savingAccounts.add(${ctx.result.items[$index]})) #end #set($checkingAccounts = []) #foreach($index in [3..4]) $util.qr($checkingAccounts.add($ctx.result.items[$index])) #end #set($transactionResult = {}) $util.qr($transactionResult.put('savingAccounts', $savingAccounts)) $util.qr($transactionResult.put('checkingAccounts', $checkingAccounts)) $util.toJson($transactionResult)

Speichern Sie den Resolver und navigieren Sie zu den Query-Abschnitten der AWS AppSync Konsole. Um die Sparkonten und die Girokonten abzurufen, führen Sie die folgende Abfrage aus:

query getAccounts { getAccounts( savingAccountNumbers: ["1", "2", "3"], checkingAccountNumbers: ["1", "2"] ) { savingAccounts { accountNumber username balance } checkingAccounts { accountNumber username balance } } }

Wir haben erfolgreich die Verwendung von DynamoDB-Transaktionen unter Verwendung von demonstriert. AWS AppSync