Introdução
Uma nova tentativa de envio de pedido não deve sobrescrever um valor existente. Uma atualização desatualizada de pagamento também não deve sobrescrever uma versão mais recente. Você fará solicitações condicionais efetivas à API, observará duplicatas e versões desatualizadas rejeitadas e comprovará que novos pedidos válidos ainda são bem-sucedidos.
Conclua primeiro Crie uma tabela DynamoDB para pedidos, incluindo itens tipados e expressões de atualização. Esta unidade nova não reutiliza tabelas ou credenciais anteriores. Use /home/labex/project, a AWS CLI oficial e AWS View.
Relação com as certificações
| Certificação | Tarefa do exame | Prática |
|---|---|---|
| Developer – Associate (DVA-C02) | Tarefa 1.3, Tarefa 1.1 | Gravações condicionais DynamoDB e concorrência otimista. |
Visão geral do laboratório

Proteja a criação do primeiro pedido
Nesta etapa, você criará um pedido apenas quando sua chave primária não estiver em uso. Um PutItem incondicional substitui o item inteiro nessa chave. Uma condição verifica o estado atual atomicamente com a gravação, portanto uma verificação separada de leitura seguida de escrita é desnecessária e permitiria condições de corrida.
Use a conexão descartável preparada e crie uma tabela independente com o ID do pedido como chave de partição String.
cd /home/labex/project
aws sts get-caller-identity
aws dynamodb create-table \
--table-name labex-d04-orders \
--attribute-definitions AttributeName=order_id,AttributeType=S \
--key-schema AttributeName=order_id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
aws dynamodb wait table-exists --table-name labex-d04-orders
Escreva um arquivo comum de solicitação da API. O heredoc entre aspas grava JSON literalmente; file:// permite que a CLI o carregue sem precisar colocar um conteúdo grande entre aspas do shell. attribute_not_exists(order_id) permite a gravação apenas se nenhum item tiver essa chave. O campo version: 1 é um valor da aplicação que você usará para proteger atualizações na etapa 3; DynamoDB não o avança automaticamente.
cat > create-order.json <<'JSON'
{
"TableName": "labex-d04-orders",
"Item": {
"order_id": {
"S": "O100"
},
"amount": {
"N": "145"
},
"status": {
"S": "NEW"
},
"version": {
"N": "1"
}
},
"ConditionExpression": "attribute_not_exists(order_id)"
}
JSON
aws dynamodb put-item --cli-input-json file://create-order.json
aws dynamodb get-item \
--table-name labex-d04-orders \
--key '{"order_id":{"S":"O100"}}' \
--consistent-read
O100 contém amount 145, NEW e version 1. A condição de ausência passa para esta chave nova. Observe AWS View na parte superior e expanda O100 para inspecionar o item efetivo.
Rejeite uma duplicata sem bloquear novos pedidos
Nesta etapa, você repetirá um ID de pedido com outro valor. Uma sobrescrita insegura mudaria O100 para 999; a condição deve rejeitá-la e preservar 145. Uma duplicata rejeitada é uma resposta de erro, não automaticamente uma resposta idempotente bem-sucedida da aplicação. A aplicação deve decidir como tratar esse erro.
Uma nova tentativa de criação não deve substituir o valor já aceito para um pedido. A condição de ausência protege essa decisão na gravação. Um filtro de leitura altera os itens retornados; uma condição de gravação decide se a alteração pode ocorrer. Cada solicitação concorrente precisa da própria condição.
Escreva a solicitação concorrente com a mesma chave e condição de ausência.
cat > duplicate-order.json <<'JSON'
{
"TableName": "labex-d04-orders",
"Item": {
"order_id": {
"S": "O100"
},
"amount": {
"N": "999"
},
"status": {
"S": "NEW"
},
"version": {
"N": "1"
}
},
"ConditionExpression": "attribute_not_exists(order_id)"
}
JSON
Repita a gravação com a mesma chave. || true permite que o terminal continue após esta falha esperada. Confira ConditionalCheckFailedException; um erro de conexão ou autorização exigiria outro diagnóstico.
aws dynamodb put-item --cli-input-json file://duplicate-order.json || true
aws dynamodb get-item \
--table-name labex-d04-orders \
--key '{"order_id":{"S":"O100"}}' \
--consistent-read
Espere ConditionalCheckFailedException e depois amount 145 e version 1 inalterados. Comprove que a mesma proteção permite outro ID de pedido em vez de negar todas as gravações.
cat > second-order.json <<'JSON'
{
"TableName": "labex-d04-orders",
"Item": {
"order_id": {
"S": "O101"
},
"amount": {
"N": "200"
},
"status": {
"S": "NEW"
},
"version": {
"N": "1"
}
},
"ConditionExpression": "attribute_not_exists(order_id)"
}
JSON
aws dynamodb put-item --cli-input-json file://second-order.json
aws dynamodb get-item \
--table-name labex-d04-orders \
--key '{"order_id":{"S":"O101"}}' \
--consistent-read
O101 é criado com amount 200, NEW e version 1. AWS View mostra ambos os pedidos enquanto amount de O100 permanece 145. Essas operações impedem uma sobrescrita não pretendida deste registro identificado por chave; elas não implementam transações de vários itens nem desduplicação de pagamentos.
Proteja uma atualização com a versão esperada
Nesta etapa, você aplicará uma transição de estado apenas à versão que leu. Uma condição de versão otimista recusa uma solicitação desatualizada em vez de sobrescrever silenciosamente uma decisão mais recente. A gravação verifica atomicamente a versão 1, define PAID e avança a versão para 2.

Escreva e execute esta solicitação UpdateItem. Aliases de nomes de expressão tratam nomes de atributos com segurança, e valores tipados fornecem as versões esperada e seguinte.
cat > pay-order.json <<'JSON'
{
"TableName": "labex-d04-orders",
"Key": {
"order_id": {
"S": "O100"
}
},
"UpdateExpression": "SET #state = :paid, #version = :next",
"ConditionExpression": "#version = :expected",
"ExpressionAttributeNames": {
"#state": "status",
"#version": "version"
},
"ExpressionAttributeValues": {
":paid": {
"S": "PAID"
},
":next": {
"N": "2"
},
":expected": {
"N": "1"
}
},
"ReturnValues": "ALL_NEW"
}
JSON
aws dynamodb update-item --cli-input-json file://pay-order.json
ALL_NEW mostra PAID e version 2 com amount 145. Repita a solicitação inalterada, que ainda espera a versão 1.
aws dynamodb update-item --cli-input-json file://pay-order.json || true
aws dynamodb get-item \
--table-name labex-d04-orders \
--key '{"order_id":{"S":"O100"}}' \
--consistent-read
Espere ConditionalCheckFailedException. A leitura final mantém PAID, version 2 e amount 145; O101 permanece NEW/version 1. Um solicitante em produção releria o estado atual e decidiria se outra atualização é apropriada, em vez de repetir a expectativa desatualizada para sempre.

Remova apenas a tabela de pedidos do exercício
Nesta etapa, você confirmará o estado final e limpará a tabela do exercício. Os arquivos JSON salvos descrevem solicitações; os itens do serviço comprovam seus efeitos efetivos. Não use o histórico de comandos nem um log de erros como prova de que a tabela foi removida.
aws dynamodb scan --table-name labex-d04-orders --consistent-read
O100 está PAID/version 2/amount 145; O101 está NEW/version 1/amount 200. Exclua apenas esta tabela e espere por sua ausência.
aws dynamodb delete-table --table-name labex-d04-orders
aws dynamodb wait table-not-exists --table-name labex-d04-orders
aws dynamodb list-tables
aws dynamodb get-item \
--table-name labex-d04-reference \
--key '{"id":{"S":"platform"}}' \
--consistent-read
Resta apenas a tabela de referência, com nota keep unchanged. Essas consultas bem-sucedidas distinguem exclusão de uma conexão malsucedida. AWS View remove a tabela de pedidos. A conexão descartável termina com esta VM.
Resumo
Você protegeu a criação de um novo pedido com uma condição de ausência, observou a rejeição de uma duplicata sem alterar o valor armazenado e permitiu outra chave nova. Depois, usou uma condição de versão esperada para aplicar uma transição de estado e rejeitar uma repetição desatualizada. Você inspecionou os valores finais efetivos dos itens antes de excluir apenas a tabela do exercício.
Para aprofundar o tema, consulte a documentação da AWS: Expressões de condição para gravações protegidas.



