

Al crear aplicaciones con Couchbase Móvil hay muchas posibilidades interesantes de integración en el servidor.
La creación de lógica de negocio para resolver conflictos de sincronización es un uso común. El sitio Pasarela de sincronización también facilita la implementación de todo tipo de operaciones basadas en eventos. Voy a explorar esto en los próximos posts.
Una aplicación puede utilizar ambos Pasarela de sincronización y Couchbase Lite llamando directamente a la API ReST de cada uno. Sin embargo, eso requiere escribir un montón de código repetitivo que no es muy divertido. PouchDB ofrece una opción compatible con JavaScript, pero ahora hay una alternativa más ligera.
No hace mucho tiempo Couchbase cambió al uso de Swagger para documentar la aplicación Couchbase Móvil APIs. Swagger hace mucho más que crear
documentación. Con una sola especificación Swagger, puedes generar documentación, código stub de servidor, casos de prueba, un sitio sandbox y mucho más. Lo mejor de todo para mí, Swagger puede generar SDKs de cliente... ¡en 40 idiomas diferentes!
En este post, voy a mostrar cómo usar el cliente Swagger Node.js. Construiremos una aplicación super simple que monitoriza cambios en documentos en Couchbase. Esto se convertirá en la base para la construcción de algunas otras cosas interesantes por venir. Vamos a sumergirnos.
Qué necesitaremos
Para seguirlo, querrás
- Node.js (estoy usando v6.9.1 en un Mac)
- Swagger JS (El cliente Swagger Node.js)
- Pasarela de sincronización Couchbase
- La especificación Sync Gateway Swagger
Asumo que ya tienes instalado Node.js.
Instalar la biblioteca Swagger JS
Desde un intérprete de línea de comandos, cambie al directorio donde guardará su proyecto.
Para obtener el cliente Swagger y sus dependencias, ejecute
1 |
$ npm instale swagger-cliente |
(Verás algunas advertencias, que puedes ignorar).
Instalar Sync Gateway
Descargue el paquete Sync Gateway para su plataforma aquí. (Si utiliza Linux y no ve un paquete para su distribución, consulte las instrucciones en
esta entrada del blog en busca de ayuda).
Para ejecutar Sync Gateway, necesitamos crear un archivo de configuración. Aquí hay una configuración simple que podemos utilizar. Copie el texto aquí y péguelo en un archivo llamado "sync-gateway-config.json", o algo similar.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ "log": ["HTTP+"], "adminInterface": "127.0.0.1:4985", "interfaz": "127.0.0.1:4984", "CORS": { "origen":["*"], "loginorigin":["*"], "cabeceras":["Tipo de contenido"], "maxAge": 1728000 }, "bases de datos": { "test": { "servidor": "morsa:", "usuarios": { "INVITADO": {"desactivado": falso, "admin_canales": ["*"] } } } } } |
Esta configuración utiliza una base de datos incorporada hecha para probar Sync Gateway. Además, el servidor sólo responderá a conexiones en localhost. Al final de este artículo encontrará recursos para obtener más información sobre la configuración de Sync Gateway.
Inicie Sync Gateway ejecutando
1 |
$ /ruta/a/sync_gateway sincronizar-pasarela-config.json |
Verás algunos registros de salida. Puede que te resulte interesante ver los registros cuando ejecutes la aplicación más tarde.
Haga una copia de la especificación Sync Gateway Swagger
Puede encontrar la especificación Swagger para la APi pública de Sync Gateway ReST (frente a la API de administración) en https://docs.couchbase.com/sync-gateway/current/_attachments/sync-gateway-admin.yaml.
Las especificaciones Swagger se almacenan como JSON. Aunque Swagger puede descargar el texto directamente, es mejor hacer una copia. Así, si la especificación cambia, no se romperá tu aplicación.
Copia la información en un archivo del directorio de tu proyecto llamado sync-gateway-spec.json, o algo similar. El archivo necesita una extensión .json para que Node pueda procesarlo.
Crear la aplicación Node.js
Vamos a montar la aplicación. Abre un nuevo archivo en el directorio de tu proyecto que termine con una extensión .js. Yo usé un archivo llamado app.js.
1 2 |
const Swagger = requiere(swagger-client); const spec = requiere('./sync-gateway-spec.json'); |
La primera línea importa el cliente Swagger y lo hace disponible. La segunda línea es un poco más inusual. Inicializa el cliente spec
a partir del JSON del archivo. Por eso es importante la extensión .json. Así es como Node reconoce que estamos
importando JSON, no un paquete normal.
El archivo de especificaciones tiene un host incorporado, pero vamos a configurarlo nosotros mismos.
1 2 3 4 |
const SYNC_GATEWAY_HOST = localhost:4984; spec.host = SYNC_GATEWAY_HOST; |
A continuación, prepararemos los parámetros para nuestra llamada a la función _cambios
punto final.
1 2 3 4 5 6 7 8 9 |
deje consulta = { db: prueba, filtro: sync_gateway/bychannel, canales: notificación, active_only: verdadero, incluir_docs: verdadero, alimentar: longpoll, tiempo de espera: 0 }; |
Fíjate que aquí tenemos una mezcla del nombre de la base de datos (test), que acaba siendo parte de la URL del endpoint, y algunas opciones que queremos configurar.
Ahora que hemos inicializado lo que necesitamos, podemos crear la instancia del cliente Swagger.
1 2 3 4 5 6 7 8 9 10 |
deje cliente = nuevo Swagger({ spec: spec, éxito: función() { monitor(cliente); }, función(error) { consola.registro(error del cliente: ', error.statusText); proceso.salida(1); } }); |
Hay varias cosas importantes que señalar aquí.
Estamos usando el cliente sincrónicamente. Si quieres, puedes usar JavaScript Promises especificando usePromise: true
. No quería hacer eso ya que no estoy haciendo ningún procesamiento real y complica el código un poco.
En lugar de spec: spec
podríamos haber listado una url para la especificación Swagger usando url:
. De nuevo, deberías evitar esto, al menos en producción, porque la especificación podría cambiar remotamente y romper tu código.
En éxito:
especifica dos funciones. Ambas son retrollamadas. La primera es llamada si la construcción tiene éxito, la segunda si falla. Estas son "globales", en cierto sentido. Estas funciones actúan como predeterminadas si no especificamos otras diferentes a la función
llamadas individuales. Eso es muy útil en caso de error.
Asignamos la instancia a una variable cliente
. La instancia de cliente se rellena de forma asíncrona. No está lista para su uso hasta que se produce la llamada de retorno de éxito. Así que tenemos la interesante construcción que cliente
se utiliza internamente en el
callback. En la versión Promises, el cliente se pasaría como argumento en el método .entonces
cláusula.
En la siguiente parte del código, utilizamos el cliente para escuchar el mensaje _cambios
punto final.
1 2 3 |
función monitor(cliente) { cliente.base de datos.obtener_cambios_db(consulta, mensaje); } |
Esto plantea un problema: ¿cómo averiguamos el nombre de la función a la que queremos llamar? No hay una correspondencia fija entre los puntos finales y los nombres de las funciones. Esta es otra característica útil de Swagger. La clase cliente se documenta por sí misma. Puedes llamar a ayuda()
en el nivel que necesites. Por ejemplo, para conocer los endpoints bajo base de datos, añade esto en tu código:
1 |
cliente.base de datos.ayuda(); |
La ayuda aparece en la línea de comandos (o en la consola de su IDE). Describirá los puntos finales y todos los parámetros posibles.
Volviendo a la llamada al cliente, vemos que pasamos tanto el nombre de la base de datos (obligatorio), como varios parámetros agrupados en el campo consulta
objeto. Esto es un poco confuso. Usted podría esperar que estos se separan, pero que no
trabajo. Ninguno de los ejemplos que encontré lo explicaba.
Proporcionamos una función de devolución de llamada mensaje
. (Observe que se utiliza si la llamada ReST tiene éxito. Confiamos en el valor por defecto para manejar los fallos).
1 2 3 4 5 |
función mensaje(respuesta) { consola.registro(respuesta.datos); consulta.desde = respuesta.obj.última_seq; monitor(cliente); } |
El callback recibe un objeto que contiene todos los detalles de la respuesta. Sólo escribí esta aplicación para mostrar la estructura de bucle necesaria para escuchar la fuente de cambios Sync Gateway. Por lo tanto, el bucle mensaje
no hace mucho. Escribimos la llamada
con fines de depuración. A continuación, queremos volver y escuchar la siguiente actualización. Sync Gateway sabe qué enviar en función de los identificadores de secuencia. Para controlar eso, usamos la función última_seq
información de nuestra última respuesta.
Ya está. Aquí está el código completo de la aplicación.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
const Swagger = requiere(swagger-client); const spec = requiere('./sync-gateway-spec.json'); const SYNC_GATEWAY_HOST = localhost:4984; spec.host = SYNC_GATEWAY_HOST; deje consulta = { db: prueba, filtro: sync_gateway/bychannel, canales: notificación, active_only: verdadero, incluir_docs: verdadero, alimentar: longpoll, tiempo de espera: 0 }; deje cliente = nuevo Swagger({ spec: spec, éxito: función() { monitor(cliente); }, función(error) { consola.registro(error del cliente: ', error.statusText); proceso.salida(1); } }); función monitor(cliente) { cliente.base de datos.obtener_cambios_db(consulta, mensaje); } función mensaje(respuesta) { consola.registro(respuesta.datos); consulta.desde = respuesta.obj.última_seq; monitor(cliente); } |
Notas finales
Puede iniciar su aplicación y probarla. Asegúrese de que Sync Gateway se está ejecutando. A continuación, ejecute
1 |
$ nodo aplicación.js |
Debería ver una respuesta en los registros de Sync Gateway y algo parecido a esto en la propia aplicación:
1 2 3 4 |
{"resultados":[ {"seq":1,"id":"_usuario/GUEST","cambios":[]} ], "last_seq":"1"} |
Ahora, añade un nuevo documento. Puedes hacerlo con cURL en la línea de comandos. Aquí tienes un ejemplo.
1 |
$ rizo -X PUT -H "Content-Type: application/json" -d '{ "clave": "valor", "canales": "notificación" }' http://localhost:4984/test/doc |
Tu aplicación Node debería mostrar algo como esto:
1 2 3 4 |
{"resultados":[ {"seq":2,"id":"doc","doc":{"_id":"doc","_rev":"1-d0efa985de274451fc7cdcf471152ce2","canales":"notificación","llave":"valor"},"cambios":[{"rev":"1-d0efa985de274451fc7cdcf471152ce2"}]} ], "last_seq":"2"} |
Otros recursos
Más información Couchbase Móvil.
Lea sobre la Pasarela de sincronización API ReST.
En Repositorio GitHub del cliente Swagger JS incluye documentación útil.
Más información sobre Swagger en http://swagger.io.
El editor Swagger en línea es realmente útil. Puedes generar SDKs de cliente aquí, o incluso probar la API directamente. Solo tienes que pegar la especificación Swagger en el editor. http://editor.swagger.io/
Hay un proyecto de la comunidad React Native Couchbase que utiliza el cliente JavaScript. Puedes encontrar algunos ejemplos interesantes en https://github.com/couchbaselabs/react-native-couchbase-lite
Posdata
Consulte más recursos en nuestra portal para desarrolladores y síganos en Twitter @CouchbaseDev.
Puede enviar preguntas a nuestro foros. Y participamos activamente en Stack Overflow.
Puede seguirme personalmente en @HodGreeley
Un tanto irónicamente, el enlace a la Swagger sync-gateway spec.json no es válido en este momento. El código aquí es muy útil e interesante. Tienes un enlace actualizado a ese archivo de especificaciones?
Parece accesible en http://docs.couchbasemobile.com/sync-gateway-public/spec.json
También docs están representando la herramienta de prueba correctamente en
https://developer.couchbase.com/documentation/mobile/current/references/couchbase-lite/rest-api/index.html
Tal vez fue un problema temporal
Creo que disparé suficientes bengalas y alguien me rescató. :P ¡Gracias!
Otra pregunta, esta vez sobre el
usePromise
en Swagger. Cómo puedo mantener la monitorización en curso mientras uso Promises (igual que en tu ejemplo sin Promise)?Reescribí los métodos para usar Promises, pero obtengo una pasada de la salida de registro que contiene la secuencia de cambios y el software sale, en lugar de permanecer vivo. ¿Alguna idea de cómo configurarlo?
cliente = nuevo Swagger({opciones})
.then(monitor)
.then(mensaje)
.catch(error)
Perdóname por practicar en mi pequeña cámara de eco. :-P
Si alguien por ahí quiere usar promesas, el patrón es devolver un nuevo cliente Swagger cada vez que se registra un mensaje. La promesa en el cliente inicial se cumplirá. El nuevo cliente tendrá que ser creado, que supervisará después de que haya hecho pendiente. No puedo postear código aquí, pero funciona encantadoramente.
Esencialmente tienes que construir un bucle donde la resolución de la Promesa pase a la siguiente etapa. Voy a escribir un ejemplo completo, pero aquí hay un fragmento para dar una idea.
nuevo Swagger({
spec: spec,
usePromise: true
})
.catch(error => die('No se ha podido crear la instancia del cliente:', error))
.then(resultado => principal(resultado))
.catch(error => die('Fallo en main:', error));
function main(cliente) {
// Código de inicio
Cambios.monitor(cliente);
}
clase Cambios {
static init(cliente) {
Cambios.query = {
db: db.db,
active_only: false,
include_docs: true,
alimentar: 'longpoll',
tiempo de espera: 0
};
}
static monitor(cliente) {
client.database.get_db_changes(Cambios.consulta)
.then(response => Cambios.parse(cliente, respuesta))
.catch(error => warn("error al recibir cambios:", error));
}
static parse(cliente, respuesta) {
for (const registro of respuesta.obj.resultados) {
// Lógica de la aplicación
Cambios.consulta.desde = registro.seq;
}
Cambios.monitor(cliente);
}
}
Estoy dispuesto a comparar notas con usted por correo electrónico, Hod. Por razones legales, no puedo publicar el código aquí, pero a través de correo electrónico de trabajo que puedo (b / c tenemos un acuerdo de confidencialidad con / CB en el archivo). Me las arreglé para conseguir que funcione en 30 líneas de ES6.
Guay, sí, me gustaría ver cómo lo enfocas. Creo que tienes mi correo electrónico, pero es sólo hod
en
…[...] Una vez definida la especificación de la API para los puntos finales, se obtienen varias funciones valiosas. Mis dos favoritas son la documentación integrable "en vivo" y las bibliotecas de clientes. Eche un vistazo a este breve vídeo para ver una demostración de algunas de las características de Swagger. Para ver un ejemplo de uso de un cliente JavaScript de Swagger, eche un vistazo a esta entrada de blog: https://www.couchbase.com/node-js-swagger-monitor-document-changes-couchbase-mobile/ […]
Gracias por el artículo, es bastante bueno, pero para ser honesto estoy un poco confundido. Creo que la declaración ... "PouchDB ofrece una opción compatible con JavaScript, pero ahora hay una alternativa más ligera" es la causa de mi confusión. Esto no me parece como una alternativa al uso de una base de datos fuera de línea como PouchDB que se sincroniza con couchbase.
Me refería a compatible en el sentido de actuar como cliente de nivel superior para la API ReST de Sync Gateway. Léelo como "tanto PouchDB como Swagger + la especificación adecuada te dan clientes ReST compatibles con Sync Gateway".
Estoy hablando del Nodo del lado del servidor aquí, así que implícitamente asumiendo que sólo estás fuera de la red cuando algo está seriamente mal. Por lo tanto, el almacenamiento local no es necesario. No es por descartar los interesantes escenarios offline, sólo para decir que no es lo que estoy tratando aquí.