En este módulo, aprovisionará una base de datos de Amazon DynamoDB y aprenderá a utilizar DynamoDB para almacenar información sobre su videojuego por turnos.

Tiempo para completar el módulo: 30 minutos


Amazon DynamoDB es un servicio de bases de datos NoSQL completamente administrado de AWS. Proporciona tiempos de respuesta en milisegundos de un solo dígito y una escalabilidad casi infinita. DynamoDB se utiliza en una amplia variedad de aplicaciones e industrias, desde el carro de compras de Amazon.com al servicio de geolocalización de Lyft y un gran número de juegos en línea.

Todas las interacciones con DynamoDB se realizan sobre HTTPS por medio de AWS Identity and Access Management (IAM) para la autenticación y autorización. Generalmente, se utiliza el SDK de AWS en su idioma de preferencia para interactuar con DynamoDB. Si utiliza las opciones de cómputo de AWS para su aplicación, como Amazon Elastic Compute Cloud (Amazon EC2) o AWS Lambda, su aplicación puede utilizar las credenciales de AWS en su entorno de cómputo para realizar solicitudes a DynamoDB.

En los siguientes pasos, aprovisionará una base de datos de DynamoDB. Luego, utilizará el SDK de AWS para JavaScript en Node.js para aprender a interactuar con su base de datos de DynamoDB.


  • Paso 1. Aprovisionar una base de datos de Amazon DynamoDB

    Primero, aprovisionemos una base de datos de DynamoDB. Una base de datos en DynamoDB también es conocida como tabla.

    Al momento de crear una tabla de DynamoDB, deberá especificar los atributos que conformarán la clave principal de su tabla. Cada registro que escribe en su tabla de DynamoDB es un elemento. Cada elemento debe incluir la clave principal de su tabla.

    El modelado de datos y el diseño de claves principales de DynamoDB es un tema importante. Sin embargo, su juego tiene un patrón de acceso simple que no requiere un modelado de datos avanzado. Por lo tanto, este tutorial no abordará temas avanzados en el modelado de datos de DynamoDB. Para obtener más información sobre el modelado de datos de DynamoDB, consulte los tutoriales Diseño de una base de datos para una aplicación móvil con Amazon DynamoDB o Modelado de datos de una aplicación de videojuegos con Amazon DynamoDB.

    En su aplicación, utilizará DynamoDB como un almacenamiento simple de valores clave. Cada videojuego tiene un atributo gameId que identifica cada juego. El atributo gameId se utiliza como la clave principal para su tabla.

    En el directorio scripts/ existe un archivo llamado create-table.sh que crea su tabla de DynamoDB mediante el uso de la Interfaz de línea de comandos de AWS (CLI de AWS). El archivo contiene lo siguiente:
     

    aws dynamodb create-table \
      --table-name turn-based-game \
      --attribute-definitions '[
        {
          "AttributeName": "gameId",
          "AttributeType": "S"
        }
      ]' \
      --key-schema '[
        {
          "AttributeName": "gameId",
          "KeyType": "HASH"
        }
      ]' \
      --provisioned-throughput '{
        "ReadCapacityUnits": 5,
        "WriteCapacityUnits": 5
      }'

    Primero, le otorga a la tabla el nombre turn-based-game. Luego, declara los atributos utilizados en la clave principal de la tabla. En este ejemplo, utilizará una clave principal simple, por lo que solo declarará un único atributo, gameId, cuyo tipo de dato es de cadena. Luego, deberá especificar su esquema de clave principal al establecer que el atributo gameId se puede ser utilizar como la clave hash de su tabla.

    Por último, deberá especificar la cantidad de unidades de capacidad de lectura y escritura que desea para su tabla. DynamoDB ofrece un modelo de precios bajo demanda en donde paga por cada solicitud de lectura y escritura hecha en su tabla. Sin embargo, el modelo de rendimiento aprovisionado puede utilizarse en la capa gratuita de AWS.

    Para crear su tabla, ejecute el siguiente comando en el terminal:

    bash scripts/create-table.sh

    Allí, debería ver los siguientes resultados:

    {
        "TableDescription": {
            "AttributeDefinitions": [
                {
                    "AttributeName": "gameId",
                    "AttributeType": "S"
                }
            ],
            "TableName": "turn-based-game",
            "KeySchema": [
                {
                    "AttributeName": "gameId",
                    "KeyType": "HASH"
                }
            ],
            "TableStatus": "CREATING",
            "CreationDateTime": 1574086642.07,
            "ProvisionedThroughput": {
                "NumberOfDecreasesToday": 0,
                "ReadCapacityUnits": 5,
                "WriteCapacityUnits": 5
            },
            "TableSizeBytes": 0,
            "ItemCount": 0,
            "TableArn": "arn:aws:dynamodb:us-east-1:955617200811:table/turn-based-game",
            "TableId": "c62cb86a-211e-4a50-a160-4a616c8f3445"
        }
    }
  • Paso 2. Guarde un elemento de ejemplo del videojuego en su tabla

    Ahora que creó su tabla, puede agregar elementos a ella. Cada videojuego está representado por un elemento en la tabla.

    El esquema para cada elemento de videojuego es el siguiente:

    Cada videojuego incluye un GameId, el cual es un identificador único para el videojuego. Los atributos User1 y User2 almacenan los nombres de usuario de los dos usuarios que participan en el videojuego. Los atributos Heap1, Heap2 y Heap3 almacenan la cantidad de objetos en cada una de las tres pilas. Por último, el atributo LastMoveBy indica el jugador que hizo la jugada más reciente.

    En el directorio scripts/ existe un archivo llamado createGame.js que agrega un videojuego de ejemplo a su tabla. El archivo contiene lo siguiente:

    const AWS = require('aws-sdk')
    const documentClient = new AWS.DynamoDB.DocumentClient()
    
    const params = {
      TableName: 'turn-based-game',
      Item: {
        gameId: '5b5ee7d8',
        user1: 'myfirstuser',
        user2: 'theseconduser',
        heap1: 5,
        heap2: 4,
        heap3: 5,
        lastMoveBy: 'myfirstuser'
      }
    }
    
    documentClient.put(params).promise()
      .then(() => console.log('Game added successfully!'))
      .catch((error) => console.log('Error adding game', error))

    Debe importar el SDK de AWS y luego crear una instancia del cliente del documento de DynamoDB. El cliente del documento es una abstracción de alto nivel sobre la API de bajo nivel de DynamoDB y facilita trabajar con los elementos de DynamoDB. Luego de crear el cliente, el script ensambla los parámetros para una llamada de API PutItem, lo que incluye el nombre de la tabla y los atributos en el elemento. Luego, llama el método put() en el cliente del documento y registra si fue exitoso o se produjo un error.

    Ejecute el siguiente comando en el terminal para ejecutar el script que inserta un videojuego en su tabla:

    node scripts/createGame.js

    Allí, debería ver los siguientes resultados:

    Game added successfully!

    Nota: Si ejecuta el comando muy rápidamente, podría aparecer un error que diga que la tabla no está disponible todavía. Espere un minuto y ejecute el comando nuevamente.

    ¡Genial! Agregó un videojuego a su tabla. En el siguiente paso, aprenderá a actualizar el videojuego para simular a un usuario que realiza un movimiento.

  • Paso 3. Actualizar un elemento de videojuego en su tabla

    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:

    1. que el usuario que solicita realizar un movimiento es uno de los dos usuarios en el juego;
    2. que el turno actual pertenece al usuario que solicita realizar el movimiento;
    3. 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:

    node scripts/performMove.js

    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:

    Error updating item:  The conditional request failed

    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.


En este módulo, usted aprovisionó una base de datos de Amazon DynamoDB para almacenar los datos de su videojuego. Aprendió sobre las claves principales en DynamoDB para modelar sus datos. Luego de crear una tabla, aprendió a introducir elementos a una tabla para almacenar el estado inicial del videojuego. Por último, aprendió cómo actualizar elementos en sus datos con una sola solicitud para evitar realizar múltiples solicitudes a DynamoDB.

En el siguiente módulo, aprenderá a utilizar Amazon Simple Notification Service (Amazon SNS) para enviar mensajes SMS y notificar a sus usuarios sobre eventos importantes en sus videojuegos.