Introducción
Un envío de pedido reintentado no debe sobrescribir un importe existente. Una actualización de pago desactualizada tampoco debe sobrescribir una versión más reciente. Realizarás solicitudes condicionales reales a la API, observarás duplicados y versiones desactualizadas rechazados y demostrarás que los pedidos nuevos válidos siguen teniendo éxito.
Completa primero Crea una tabla DynamoDB para pedidos, incluidos los elementos tipados y las expresiones de actualización. Esta unidad nueva no reutiliza tablas ni credenciales anteriores. Utiliza /home/labex/project, AWS CLI oficial y AWS View.
Relación con las certificaciones
| Certificación | Tarea del examen | Práctica |
|---|---|---|
| Developer – Associate (DVA-C02) | Tarea 1.3, Tarea 1.1 | Escrituras condicionales DynamoDB y concurrencia optimista. |
Vista general del laboratorio

Protege la creación del primer pedido
En este paso, crearás un pedido solo cuando su clave primaria no esté utilizada. Un PutItem incondicional reemplaza todo el elemento de esa clave. Una condición comprueba el estado actual de forma atómica con la escritura, así que una comprobación independiente de lectura seguida de escritura es innecesaria y permitiría condiciones de carrera.
Utiliza la conexión desechable preparada y crea una tabla independiente con el ID de pedido como clave de partición 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
Escribe un archivo normal de solicitud de API. El heredoc entre comillas escribe JSON literalmente; file:// permite que la CLI lo cargue sin tener que entrecomillar una carga grande en el shell. attribute_not_exists(order_id) permite la escritura solo si ningún elemento tiene esa clave. El campo version: 1 es un valor de la aplicación que utilizarás para proteger actualizaciones en el paso 3; DynamoDB no lo incrementa automáticamente.
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 contiene amount 145, NEW y version 1. La condición de ausencia se cumple para esta clave nueva. Observa AWS View en la parte superior y despliega O100 para inspeccionar el elemento real.
Rechaza un duplicado sin bloquear pedidos nuevos
En este paso, volverás a enviar un ID de pedido con otro importe. Una sobrescritura insegura cambiaría O100 a 999; la condición debe rechazarla y conservar 145. Un duplicado rechazado es una respuesta de error, no automáticamente una respuesta idempotente correcta de aplicación. La aplicación debe decidir cómo tratar ese error.
Reintentar una creación no debería reemplazar el importe ya aceptado para un pedido. La condición de ausencia protege esa decisión durante la escritura. Un filtro de lectura cambia los elementos devueltos; una condición de escritura decide si la modificación puede ocurrir. Cada solicitud competidora necesita su propia condición.
Escribe la solicitud competidora con la misma clave y condición de ausencia.
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
Repite la escritura con la misma clave. || true permite que la terminal continúe después de este fallo esperado. Comprueba que aparece ConditionalCheckFailedException; un error de conexión o autorización requeriría otro 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
Espera ConditionalCheckFailedException y después amount 145 y version 1 sin cambios. Demuestra que la misma protección permite otro ID de pedido en lugar de denegar todas las escrituras.
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 se crea con amount 200, NEW y version 1. AWS View muestra ambos pedidos mientras el importe de O100 sigue siendo 145. Estas operaciones evitan una sobrescritura involuntaria de este registro identificado por clave; no implementan transacciones de varios elementos ni deduplicación de pagos.
Protege una actualización con la versión esperada
En este paso, aplicarás una transición de estado únicamente a la versión que leíste. Una condición de versión optimista rechaza una solicitud desactualizada en lugar de sobrescribir silenciosamente una decisión más reciente. La escritura comprueba atómicamente version 1, establece PAID e incrementa version a 2.

Escribe y ejecuta esta solicitud UpdateItem. Los alias de nombres de expresión tratan los nombres de atributos de forma segura y los valores tipados proporcionan las versiones esperada y siguiente.
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 muestra PAID y version 2 con amount 145. Repite la solicitud sin cambios, que todavía espera version 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
Espera ConditionalCheckFailedException. La lectura final conserva PAID, version 2 y amount 145; O101 permanece en NEW/version 1. Un llamante de producción volvería a leer el estado actual y decidiría si corresponde otra actualización, en lugar de reintentar indefinidamente la expectativa desactualizada.

Elimina únicamente la tabla de pedidos propia
En este paso, confirmarás el estado final y limpiarás la tabla propia. Los archivos JSON guardados describen solicitudes; los elementos del servicio establecen sus efectos reales. No utilices el historial de comandos ni un registro de errores como prueba de que se eliminó la tabla.
aws dynamodb scan --table-name labex-d04-orders --consistent-read
O100 está en PAID/version 2/amount 145; O101 está en NEW/version 1/amount 200. Elimina únicamente esta tabla y espera a su ausencia.
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
Solo queda la tabla de referencia, con la nota keep unchanged. Estas consultas correctas distinguen la eliminación de una conexión fallida. AWS View elimina la tabla de pedidos. La conexión desechable termina con esta VM.
Resumen
Protegiste la creación de pedidos nuevos con una condición de ausencia, observaste un duplicado rechazado sin cambiar el importe almacenado y permitiste otra clave nueva. Después utilizaste una condición de versión esperada para aplicar una transición de estado y rechazar una repetición desactualizada. Inspeccionaste los valores finales reales de los elementos antes de eliminar únicamente la tabla propia.
Para ampliar este tema, consulta la referencia de AWS: Expresiones de condición para escrituras protegidas.



