As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.
AWS AppSync suporta o uso de operações de transação do Amazon DynamoDB em uma ou mais tabelas em uma única região. As operações compatíveis são TransactGetItems
e TransactWriteItems
. Ao usar esses recursos no AWS AppSync, você pode realizar tarefas como:
-
Enviar uma lista de chaves em uma única consulta e retornar os resultados de uma tabela
-
Ler os registros de uma ou mais tabelas em uma única consulta
-
Gravando registros em transações em uma ou mais tabelas de uma all-or-nothing forma
-
Executar transações quando algumas condições são atendidas
Permissões
Como outros resolvedores, você precisa criar uma fonte de dados AWS AppSync e criar uma função ou usar uma existente. Como operações de transação exigem diferentes permissões em tabelas do DynamoDB, é necessário conceder as permissões de função configuradas para ações de leitura e gravação:
{ "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/*" ] } ] }
nota
As funções são vinculadas às fontes de dados em AWS AppSync, e os resolvedores nos campos são invocados em uma fonte de dados. As fontes de dados configuradas para buscar no DynamoDB têm apenas uma tabela especificada, para manter a configurações simples. Portanto, ao executar uma operação de transação para várias tabelas em um único resolvedor, que é uma tarefa mais avançada, é necessário conceder acesso à função na fonte de dados para qualquer tabela com a qual o resolvedor interage. Isso é feito no campo Recurso na política do IAM acima. A configuração das chamadas de transação nas tabelas é feita no código de resolvedor, descrita abaixo.
Fonte de dados
Para simplificar, usaremos a mesma fonte de dados para todos os resolvedores usados neste tutorial.
Teremos duas tabelas chamadas savingAccounts e checkingAccounts, ambas com accountNumber
como chave de partição, e uma tabela transactionHistory com transactionId
como chave de partição. É possível usar os comandos da CLI abaixo para criar suas tabelas. Substitua region
pela região.
Com a 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
No AWS AppSync console, em Fontes de dados, crie uma nova fonte de dados do DynamoDB e nomeie-a. TransactTutorial Selecione savingAccounts como tabela (a tabela especificada não importa ao usar transações). Selecione para criar uma fonte de dados. Você pode revisar a configuração da fonte de dados para ver o nome da função gerada. No console do IAM, você pode adicionar uma política em linha que permite que a fonte de dados interaja com todas as tabelas.
Substitua region
e accountID
por sua região e seu ID da conta:
{
"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/*"
]
}
]
}
Transações
Neste exemplo, o contexto é uma transação bancária clássica, onde usaremos TransactWriteItems
para:
-
Transferir dinheiro de contas poupanças para contas correntes
-
Gerar novos registros para cada transação
E, então, vamos usar TransactGetItems
para recuperar detalhes de contas poupanças e contas correntes.
Atenção
TransactWriteItems
não é compatível quando usado com detecção e resolução de conflitos. Essas configurações devem ser desativadas para evitar possíveis erros.
Nós definimos nosso esquema GraphQL da seguinte forma:
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 - Preencher contas
Para transferir dinheiro entre contas, precisamos preencher a tabela com os detalhes. Usaremos a operação do GraphQL Mutation.populateAccounts
para fazer isso.
Na seção Esquema, clique em Anexar ao lado da operação Mutation.populateAccounts
. Escolha a fonte de dados do TransactTutorial
e escolha Criar.
Agora use o seguinte código:
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 }
}
Salve o resolvedor e navegue até a seção Consultas do AWS AppSync console para preencher as contas.
Execute a seguinte mutação:
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
}
}
}
Nós preenchemos três contas poupanças e três contas correntes em uma mutação.
Use o console do DynamoDB para confirmar se os dados aparecem nas tabelas savingAccounts e checkingAccounts.
TransactWriteItems - Transferir dinheiro
Anexe um resolvedor à mutação transferMoney
com o código a seguir. Para cada transferência, precisamos de um modificador de sucesso para contas correntes e de poupança, e precisamos rastrear a transferência nas transações.
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 }
}
Agora, navegue até a seção Consultas do AWS AppSync console e execute a mutação TransferMoney da seguinte forma:
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
}
}
}
Nós enviamos três transações bancárias em uma mutação. Use o console do DynamoDB para validar se os dados aparecem nas tabelas savingAccounts, checkingAccounts e transactionHistory.
TransactGetItems - Recuperar contas
Para recuperar os detalhes das contas poupança e corrente em uma única solicitação transacional, anexaremos um resolvedor à operação Query.getAccounts
do GraphQL em nosso esquema. Selecione Anexar e escolha a mesma fonte de dados do TransactTutorial
criada no início do tutorial. Use o seguinte código:
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 }
}
Salve o resolvedor e navegue até as seções Consultas do console do AWS AppSync . Para recuperar as contas poupança e corrente, execute a seguinte consulta:
query getAccounts {
getAccounts(
savingAccountNumbers: ["1", "2", "3"],
checkingAccountNumbers: ["1", "2"]
) {
savingAccounts {
accountNumber
username
balance
}
checkingAccounts {
accountNumber
username
balance
}
}
}
Demonstramos com sucesso o uso das transações do DynamoDB usando. AWS AppSync