Hace unos años, Brett Lawson hizo una gran serie de blogs sobre el uso de Couchbase Server y Node.js para el desarrollo de un framework de servidor de juegos. Desde entonces, el SDK de Node.js para Couchbase ha crecido significativamente de la versión 1.x a la 2.x.

En este artículo vamos a revisar esos tres posts originales y cambiarlos para que estén al día con los últimos estándares de Node.js y Express Framework, así como con la última versión del SDK de Node.js de Couchbase.

Requisitos previos

  • Node.js 0.12
  • Servidor Couchbase 4.0

Preparación del proyecto

Ya sea en Mac, Windows o Linux, la creación de una nueva aplicación Express Framework debe ser coherente entre ellos. Cree un nuevo directorio llamado gameapi-nodejs probablemente en su Escritorio y desde su Terminal (Mac / Linux) o Símbolo del sistema (Windows), ejecute el siguiente comando:

Responda a las preguntas lo mejor que pueda. Por supuesto, el directorio del proyecto debe ser su directorio actual en el Símbolo del sistema o Terminal para que esto tenga éxito. Como alternativa al comando, puede crear y rellenar manualmente este archivo. Cree un nuevo archivo llamado package.json en el directorio de su proyecto y llénelo con lo siguiente:

No hemos terminado. Tenemos que instalar las dependencias del proyecto antes de que podamos empezar a planificar esta aplicación. Desde el símbolo del sistema o Terminal, ejecute el siguiente comando:

Esto instalará Express Framework, el SDK de Couchbase Node.js, Forge para hash de contraseñas, UUID para generar valores únicos, y el middleware body-parser para manejar datos POST codificados en URL y JSON.

Preparación de la base de datos

Antes de empezar a codificar, Couchbase Server debe estar instalado con un bucket llamado juego-muestra creado.

Dado que este proyecto va a hacer uso de una de las principales características de Couchbase 4.0, necesitaremos configurar el bucket para crear un índice primario. Si estás usando una máquina Linux, Mac o Windows, esto se puede lograr fácilmente a través del cliente Couchbase Query (CBQ).

Mac

Para abrir CBQ en Mac, desde el Terminal, ejecute lo siguiente:

Windows

Para abrir CBQ en Windows, desde el símbolo del sistema, ejecute lo siguiente:

Creación de un índice primario

Con CBQ abierto, ejecute lo siguiente:

Tu cubo ya está listo para el resto del proyecto.

Estructura del proyecto

Nuestro proyecto va a constar de lo siguiente:

Artículo Padres Descripción
modelos Todos los archivos de clase de la base de datos irán aquí
rutas Todas las definiciones de los puntos finales de la API irán aquí
accountmodel.js modelos Crear y recuperar información sobre cuentas
sessionmodel.js modelos Autenticación de usuarios y mantenimiento de la información de sesión
statemodel.js modelos Crear, actualizar y recuperar información sobre el estado del juego
rutas.js rutas Todos los endpoints para GET, POST, PUT estarán aquí
app.js Información sobre la configuración del servidor
config.json Variables estáticas
paquete.json Información sobre la dependencia

Conceptos básicos

Antes de adentrarnos en la lógica del servidor de juegos Node.js, lo mejor es configurar la aplicación base Express Framework.

En la raíz del proyecto, cree y abra un archivo llamado config.json ya que contendrá información estática como la información de conectividad de Couchbase. Incluya lo siguiente cuando esté abierto:

En la raíz del proyecto, cree y abra un archivo llamado app.js ya que contendrá toda la información básica sobre el funcionamiento del servidor Node.js. Incluye lo siguiente cuando hayas abierto el archivo:

Vamos a desglosar lo que vemos aquí. Las primeras líneas son nosotros incluyendo las dependencias en nuestra aplicación. No hay nada especial. Lo que es importante es lo siguiente:

Esto significa que vamos a analizar datos JSON y datos codificados en URL de los cuerpos de las peticiones. En particular las peticiones POST y PUT. Lo siguiente que vamos a hacer es inicializar el cluster de Couchbase en la aplicación y abrir un único bucket para su uso dentro de la aplicación:

Incluyendo module.exports.bucket estamos diciendo que vamos a usarlo a través de la aplicación. Ahora en otros archivos JavaScript, si queremos acceder al cubo podemos simplemente hacer:

A continuación verás que incluimos nuestro pronto creado rutas/routes.js y pasándole el archivo aplicación como uno de los argumentos. Lo que esto hace será obvio pronto.

Por último, llamando a app.listen le estamos diciendo a Node.js que escuche en el puerto 3000 para peticiones. La aplicación es casi utilizable en su estado más básico. Crear y abrir rutas/routes.js y añade las siguientes líneas:

La aplicación se puede ejecutar ahora ejecutando node app.js desde el símbolo del sistema o el terminal. Aterrizar en http://localhost:3000 debería mostrar el mensaje "Not a valid endpoint".

El modelo de datos de la API

Antes de sumergirse en el código que importa, es mejor saber cómo se verán los datos en Couchbase. Para cualquier usuario, habrá cuatro documentos con el siguiente aspecto:

El documento del usuario

El documento de usuario contendrá toda la información sobre un usuario. Para esta aplicación esa información será un nombre, un nombre de usuario y una contraseña.
El nombre de este documento llevará el prefijo usuario:: y se le añade un valor uid único. Esta estrategia de nomenclatura de documentos utiliza lo que se denomina claves compuestas.

El documento del nombre de usuario

El documento de nombre de usuario contendrá sólo el valor uid que se encuentra en el documento de usuario. El propósito del documento de nombre de usuario puede ser pensado como un documento de método de inicio de sesión. Por ejemplo, podría representar un simple inicio de sesión en el que el usuario introduce un nombre de usuario y una contraseña. Dado que el documento contiene el uid de enlace, puede vincularse al documento de usuario. El documento de nombre de usuario lleva el prefijo nombre de usuario:: y se le añade el nombre de usuario real. Se puede utilizar una estrategia similar si se utilizan Facebook o Twitter como métodos de inicio de sesión y vincularlos también a través del campo uid.

El documento de sesión

El documento de sesión es un documento de caducidad automática que actúa como ruta del usuario hacia información más segura. En teoría, el front-end del usuario almacenará el valor sid y lo pasará entre endpoints protegidos. Con él, se puede acceder a un uid vinculado a un usuario.

El Documento de Estado

El documento de estado contendrá información sobre el estado particular del juego. Por ejemplo, si al personaje le quedan cinco vidas y veinte pociones, esa información se guardará aquí. Hay información de versión para evitar conflictos entre dos sesiones de juego activas que se guardan bajo la misma cuenta.

Creación del modelo de cuenta

El modelo de cuenta servirá para tres fines concretos:

  • Crear una cuenta de usuario
  • Recuperación de una cuenta de usuario
  • Comparar una contraseña con hash con una contraseña sin hash

Antes de empezar a codificar, necesitamos poner nuestros includes en orden. Añade lo siguiente a la parte superior del archivo models/accountmodel.js file:

Basándonos en el modelo de datos visto anteriormente, para crear una cuenta de usuario se necesitará un nombre, un nombre de usuario y una contraseña. Con esa información en la mano, la contraseña será hash, y la información del usuario se almacenará junto a un documento de referencia como este:

Observe que en el código anterior, primero intentamos insertar un nuevo documento de referencia. Si falla (puede que ya exista), no se guardará ningún documento y en su lugar se devolverá el mensaje de error. Tanto si es un éxito como un fracaso, la llamada de retorno del archivo de rutas se ejecuta para mostrar cualquier tipo de respuesta al solicitante.

En términos de lectura de datos de usuario, una de dos cosas podría suceder. Podríamos pasar un nombre de usuario porque estamos haciendo un simple login of-sorts, o podríamos pasar un id de usuario. Depende de lo que estamos después. Digamos que sólo estamos iniciando sesión con el nombre de usuario, es probable que desee llamar a una función como esta:

Fíjate en que estamos usando una consulta N1QL, nueva en Couchbase 4.0. Es muy similar al SQL tradicional y además nos da la comodidad de no tener que crujir o formatear datos en la capa de aplicación. Couchbase Server hará todo esto por nosotros. No obstante, tenemos la opción de solicitar datos como en versiones anteriores de Couchbase y otras plataformas NoSQL.

En la sentencia N1QL anterior, estamos seleccionando un documento con la clave compuesta anexada a nuestro nombre de usuario en texto plano. Se produce una unión con la propiedad uid del documento usernames (clave externa) y el documento users (clave primaria).

Esto nos lleva a la validación de una contraseña. Aquí no se hace ninguna llamada a la base de datos. Simplemente vamos a tomar una contraseña en bruto, hash, a continuación, comparar el hash con la contraseña almacenada.

Para hacer models/accountmodel.js utilizable en nuestro archivo de rutas debemos exportarlo así en la parte inferior del
models/accountmodel.js código:

Creación del modelo de sesión

El modelo de sesión servirá para tres fines concretos:

  • Crear una sesión de usuario
  • Recuperación de una sesión de usuario
  • Validación de una sesión de usuario

Antes de empezar a codificar, necesitamos poner nuestros includes en orden. Añade lo siguiente a la parte superior del archivo modelos/sessionmodel.js file:

Crear una sesión

Cuando un usuario desea crear una sesión, debe proporcionar un uid. Con esto en la mano, se crea un id de sesión único y se inserta en la base de datos con una caducidad. Cuando expire, se eliminará automáticamente de Couchbase sin intervención del usuario, cerrando así su sesión.

Autenticación de un usuario

Una vez creada la sesión de usuario, el identificador de sesión debe utilizarse cada vez que el usuario desee acceder a un punto final protegido.

En el código anterior, la función recibirá un identificador de sesión que utilizará para comprobar si ya existe una sesión. En caso afirmativo, restablecerá el tiempo de expiración de la sesión y devolverá el uid asociado a la misma. La obtención de la información de la sesión puede verse de la siguiente manera:

No está mal, ¿verdad? Finalmente puedes ver que el reinicio de sesión ocurre de manera similar:

El método táctil no añadirá tiempo, sino que lo restablecerá. En este caso, reiniciará el temporizador a una hora.

Para hacer modelos/sessionmodel.js utilizable en nuestro archivo de rutas debemos exportarlo así en la parte inferior del modelos/sessionmodel.js código:

Creación del modelo de Estado

El modelo estatal servirá para dos fines concretos:

  • Crear o actualizar un estado guardado
  • Recuperar un estado guardado por nombre

Antes de empezar a codificar, necesitamos poner nuestros includes en orden. Añade lo siguiente a la parte superior del archivo models/statemodel.js file:

Creación de un estado de guardado

El objetivo de crear o actualizar un save-state es que primero comprobemos si existe. Si no existe, lo crearemos. Si existe, entonces obtendremos cualquier información que exista, la cambiaremos, y luego reemplazaremos lo que exista actualmente en la base de datos. Todo esto se hace mientras se incrementa la versión del estado para evitar conflictos entre los guardados del juego. No realmente para evitar conflictos al guardar en Couchbase, sólo para asegurarnos de que no coges el juego en dos dispositivos y anulas los datos del juego con un guardado mucho más antiguo.

Véase el upsert allí. En Couchbase eso significa crear si no existe, o reemplazar si existe. Muy conveniente para cosas como guardar estados para un juego.

Conseguir los Estados

Esto nos deja con la obtención de cualquier save-state que hayamos creado.

El concepto detrás de esto es que estamos haciendo una búsqueda de documentos basada en un ID de usuario. Si el documento de estado para un uid en particular existe, entonces haz una búsqueda en el array asociativo para ver si el nombre del estado existe. Si existe, devuelve cualquier contenido de estado que exista para el nombre.

Para hacer models/statemodel.js utilizable en nuestro archivo de rutas debemos exportarlo así en la parte inferior del models/statemodel.js código:

Creación de las rutas API

Ya hemos creado todos los modelos de datos necesarios, así que es hora de encadenarlos con rutas accesibles para el usuario. Volviendo al modelo rutas/routes.js empezaremos por añadir las rutas del modelo de cuenta:

El endpoint anterior espera una petición POST con un parámetro de cuerpo nombre, nombre de usuario y contraseña Estamos a la escucha de POST porque es la mejor práctica utilizar POST al crear o insertar datos a través de una petición HTTP. Si existen los tres, entonces el endpoint AccountModel.create() y, finalmente, devuelve un error o un resultado en función del éxito del método. Si al menos uno de los parámetros requeridos no existe, se devuelve un error. Se puede ver una lista de códigos de error aquí.

Un endpoint para obtener información del usuario no es tan importante en este ejemplo, así que saltaremos directamente a autenticar al usuario y crear una sesión. En el rutas/routes.js añada lo siguiente:

El punto final de autenticación espera un nombre de usuario y una contraseña. Si se encuentran ambos, se buscará el usuario. Si se encuentra el usuario, se realiza una comparación de la contraseña y, si tiene éxito, se creará una sesión.

Los dos últimos puntos finales de la API que nos son útiles son para obtener y crear estados guardados. Comenzando con la creación de un endpoint de estado guardado, en su rutas/routes.jsañade lo siguiente:

El punto final anterior espera un parámetro de URL que represente el nombre del estado, un parámetro de consulta que represente la versión actual del estado y un cuerpo de solicitud que puede contener cualquier JSON imaginable, ya que representa los datos del juego que merece la pena guardar.

Por último, nos queda obtener los estados que se han guardado.

El punto final anterior espera un parámetro URL que represente el estado de guardado concreto que se desea encontrar. Por supuesto, también espera que el usuario se autentique primero.

Probar la API

Los puntos finales de la API que creamos en el módulo rutas/routes.js se puede probar de varias maneras. Dos de mis formas favoritas de probarlo son con la extensión Postman para Chrome o con cURL. Pruébalo tú mismo usando cURL:

Arriba seguimos adelante y creamos una nueva cuenta de usuario

Arriba creamos una sesión de usuario. Esta misma estrategia se puede aplicar para los otros puntos finales también.

Conclusión

Usando Node.js y el SDK de Couchbase Server, puedes crear fácilmente una API backend para tus juegos. En Couchbase 4.0 ahora tienes la libertad de usar N1QL como opción para consultar datos en tu aplicación.

La aplicación Node.js completa sobre la que se ha escrito en este artículo puede descargarse gratuitamente de la dirección Couchbase Labs GitHub repositorio.

Autor

Publicado por Nic Raboy, Defensor del Desarrollador, Couchbase

Nic Raboy es un defensor de las tecnologías modernas de desarrollo web y móvil. Tiene experiencia en Java, JavaScript, Golang y una variedad de frameworks como Angular, NativeScript y Apache Cordova. Nic escribe sobre sus experiencias de desarrollo relacionadas con hacer el desarrollo web y móvil más fácil de entender.

5 Comentarios

  1. Martin Micunda julio 18, 2015 a 3:52 pm

    Hola,

    ¿Sigue siendo necesario habilitar N1QL en couchbase 4 ejecutando \'bucket.enableN1ql(\'localshot:8093\');\'? Gracias

    1. Matt Ingenthron julio 18, 2015 a 6:12 pm

      nope, sólo funciona con el último SDK

      1. quiero preguntarle por el error de un cliente:\"

        [com.couchbase.client.deps.io.netty.util.ResourceLeakDetector] FALLO: ByteBuf.release() no fue llamado antes de ser recolectado. Habilite el informe avanzado de fugas para averiguar dónde se produjo la fuga. Para habilitar el informe avanzado de fugas, especifique la opción JVM \'-Dcom.couchbase.client.deps.io.netty.leakDetectionLevel=advanced\' o llame a ResourceLeakDetector.setLevel()\".
        ¿Cuál es el problema?

  2. Hola,

    ¿Se puede usar N1QL sólo para consultas o se puede usar para hacer los UPSERT\'s e INSERT\'s? Gracias

    1. En este momento INSERT, UPDATE, DELETE, UPSERT son beta. Puedes usarlos, pero hasta que no salgan de la beta no recomendamos usarlos en un entorno de producción.

      http://developer.couchbase.com

      Lo mejor,

Dejar una respuesta