Ahora que tiene un elemento de videojuego en su tabla, podrá aprender cómo simular a un jugador que realiza una jugada en un juego en progreso.
Hay dos maneras para realizar esta operación. En la primera, recupera el elemento mediante el uso de la API GetItem. Luego, actualiza el elemento del videojuego en su aplicación según el movimiento que realiza el jugador. Por último, reemplaza el elemento existente en DynamoDB mediante la API PutItem. Aunque esta opción funciona correctamente, requiere varias solicitudes a su tabla de DynamoDB y existe el riesgo de sobrescribir los cambios realizados que ocurrieron entre la recuperación y la reescritura de su elemento de videojuego.
La segunda manera de realizar esta operación es mediante la llamada de API UpdateItem en DynamoDB. Con la API UpdateItem, puede actualizar el elemento de DynamoDB en su lugar a través de una sola solicitud. Debe especificar el elemento que desea cambiar, los atributos a cambiar y las condiciones que desee establecer en el elemento. Este es el método preferido para realizar cambios en los elementos ya que no requiere múltiples llamadas a su base de datos.
En el directorio scripts/ existe un archivo llamado performMove.js que posee los siguientes contenidos:
const AWS = require('aws-sdk')
const documentClient = new AWS.DynamoDB.DocumentClient()
const performMove = async ({ gameId, user, changedHeap, changedHeapValue }) => {
if (changedHeapValue < 0 ) {
throw new Error('Cannot set heap value below 0')
}
const params = {
TableName: 'turn-based-game',
Key: {
gameId: gameId
},
UpdateExpression: `SET lastMoveBy = :user, ${changedHeap} = :changedHeapValue`,
ConditionExpression: `(user1 = :user OR user2 = :user) AND lastMoveBy <> :user AND ${changedHeap} > :changedHeapValue`,
ExpressionAttributeValues: {
':user': user,
':changedHeapValue': changedHeapValue,
},
ReturnValues: 'ALL_NEW'
}
try {
const resp = await documentClient.update(params).promise()
console.log('Updated game: ', resp.Attributes)
} catch (error) {
console.log('Error updating item: ', error.message)
}
}
performMove({ gameId: '5b5ee7d8', user: 'theseconduser', changedHeap: 'heap1', changedHeapValue: 3 })
Este script es un poco complicado. Veámoslo paso por paso.
Al igual que con el script anterior, debe importar el SDK de AWS y crear una instancia del cliente de documento de DynamoDB.
Luego, debe definir un método llamado performMove. El método es similar al método interno que debe utilizarse en su aplicación cuando un usuario solicita realizar un movimiento. El script ensambla los parámetros para la llamada a la API UpdateItem. Primero, cambia dos atributos en el videojuego; el último usuario en realizar un movimiento y la cantidad de elementos en la pila cambiada.
Los parámetros de la API UpdateItem realizarán algunas aseveraciones sobre el estado actual del juego. Se evaluará la ConditionExpression antes de que el elemento se actualice para confirmar que este se encuentra en el estado que desea. Deberá realizar las siguientes tres aseveraciones en su expresión de condición:
- que el usuario que solicita realizar un movimiento es uno de los dos usuarios en el juego;
- que el turno actual pertenece al usuario que solicita realizar el movimiento;
- que la pila que se cambia posee un valor actual más alto que el valor al cual se cambia.
Por último, los parámetros establecen un ReturnValue de ALL_NEW, lo cual significa que DynamoDB regresa el elemento completo luego de que sus valores se hayan actualizado. Cuando tenga esto, su aplicación podrá evaluar el juego para ver si hay un ganador.
Al final del archivo hay un ejemplo sobre cómo llamar a este método en su aplicación. Puede ejecutar el script con el siguiente comando:
Allí, debería ver los siguientes resultados:
Updated game: { heap2: 4,
heap1: 3,
heap3: 5,
gameId: '5b5ee7d8',
user2: 'theseconduser',
user1: 'myfirstuser',
lastMoveBy: 'theseconduser' }
Puede ver que la escritura fue exitosa y que se actualizó el juego.
Intente ejecutar el script nuevamente en su terminal. Debería ver el siguiente resultado:
Se produjo un error en sus solicitudes condicionales esta vez. El usuario que realiza la solicitud (theseconduser) fue el usuario con el movimiento más reciente. Además, la pila cambiada (heap1) ya tenía un valor de 3, por lo que el usuario no cambió nada. Debido a esto, la solicitud fue rechazada.