Acabamos de lanzar Couchbase Mobile 1.1 y con esta nueva versión vienen muchos novedades. En esta entrada de blog, echaremos un vistazo a los webhooks de Sync Gateway y pensaremos en algunos ejemplos concretos para utilizarlos.
Webhooks
Antes de la versión 1.1, la única forma de añadir lógica personalizada en forma de plugins a Sync Gateway era escuchar la fuente de cambios. Si bien este enfoque sigue funcionando, no es el más fácil de configurar. Con webhooks, sólo tiene que proporcionar una función de filtro y la dirección URL para publicar el evento. A continuación, manejar el evento con el lenguaje back-end de su elección (NodeJS, Java, Go, Ruby...).
Los webhooks pueden utilizarse para muchos casos diferentes:
- Mensajería: notificaciones específicas para informar a los usuarios de acontecimientos importantes.
- ProgramaciónInicio de grandes tareas que pueden estar ejecutándose en un web worker.
- Lógica personalizadaFunción de sincronización: amplía las capacidades de la función de sincronización utilizando un webhook para realizar tareas adicionales en el documento.
En la siguiente sección, se centrará en la creación de la función de notificaciones push para una aplicación de noticias con el fin de informar a los usuarios cuando se publiquen nuevos artículos que coincidan con sus temas de interés. Este tutorial se ha extraído del Couchbase por ejemplo repositorio.
Consideraciones sobre la arquitectura
La notificación push es una pista visual para que el usuario sepa que hay nuevos contenidos disponibles, pero también podría ser para que la propia aplicación extraiga los nuevos artículos del servidor:
La razón por la que utilizamos la API Web Push en lugar de una replicación pull continua con Sync Gateway para comprobar si hay nuevos artículos es que puede funcionar incluso cuando el navegador está cerrado. En comparación con un web socket o un sondeo largo, que solo se mantendrán vivos mientras el navegador y la página web se mantengan abiertos.
Escenarios
Existen diferentes escenarios para enviar una notificación push:
- Mensajería de grupo: este concepto se introdujo en GCM para enviar notificaciones hasta a 20 dispositivos simultáneamente. Es muy adecuado para enviar notificaciones a todos los dispositivos que pertenecen a un mismo usuario.
- Arriba y abajo: un usuario actualiza un documento y otros usuarios deben ser notificados de ello a través de una Notificación Push.
Modelo de datos
Empecemos por el documento más pequeño, un documento de Perfil que contiene tokens de registro de los dispositivos del usuario y temas de interés:
1 2 3 4 5 6 7 8 9 10 |
{ "tipo": "perfil", "nombre": "Oliver", "suscripción": "gratis", // otros valores "caducado", "prima" "temas": ["g20", "ciencia", "nsa", "diseño"], "registration_ids": ["AP91DIwQ", "AP91W9kX"] } |
Y el documento Artículo puede tener las siguientes propiedades:
1 2 3 4 5 6 7 8 9 |
{ "tipo": "artículo", "título: "Herramientas de diseño para desarrolladores", "contenido": "...", "tema": "diseño" } |
Mensajería de grupo
Imagina que un usuario está registrado en una cuenta freemium e introduce un código de invitación para acceder al plan premium durante un tiempo limitado. Sería bueno enviar una notificación a todos los dispositivos del usuario para obtener el contenido adicional.
Breve: Envía una notificación puntual a los usuarios freemium que también tengan un código de invitación para desbloquear otros dispositivos.
Descargar el 1.1 lanzamiento de Sync Gateway. Encontrará el binario de Sync Gateway en la carpeta papelera y ejemplos de archivos de configuración en la carpeta ejemplos carpeta. Copie la carpeta ejemploconfig.json en la raíz del proyecto:
1 2 3 4 |
cp ~/Descargas/couchbase-sincronizar-pasarela/ejemplos/exampleconfig.json /ruta/a/proj/sincronizar-pasarela-config.json |
Añade tres usuarios en el archivo de configuración:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
{ "log": ["CRUD", "HTTP+"], "bases de datos": { "db": { "servidor": "morsa:", "usuarios": { "zack": { "contraseña": "letmein" }, "ali": { "contraseña": "letmein" }, "adam": { "contraseña": "letmein" }, "INVITADO": {"desactivado": verdadero} } } } } |
Añade un web hook con las siguientes propiedades en el directorio db objeto:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
"event_handlers": { "documento_cambiado": [ { "manipulador": "webhook", "url": "http://localhost:8000/invitecode", "filtro": `función(doc) { si (doc.tipo == "perfil" && doc.código_invitación) { devolver verdadero; } devolver falso; }` } ] } |
Inicie Sync Gateway:
1 2 3 4 |
$ ~/Descargas/couchbase-sincronizar-pasarela/papelera/sincronizar_pasarela ./sincronizar-pasarela-config.json |
Crear un nuevo archivo main.go para gestionar el webhook:
1 2 3 4 5 6 7 8 9 |
func principal() { http.HandleFunc("/invitecode", func(w http.EscritorRespuesta, r *http.Solicitar) { registro.Imprimir("ping") }) registro.Fatal(http.ListenAndServe(":8000", nil)) } |
Inicie el servidor Go:
1 2 3 4 |
$ ir ejecute principal.ir |
Utilizando curl, haga una petición POST a :4984/db/bulk_doc para guardar 3 documentos de Perfil simultáneamente:
1 2 3 4 5 6 |
rizo -H Content-Type: application/json' -vX POST http://localhost:4985/db/_bulk_docs --datos @perfiles.json |
NOTA: Para ahorrar espacio en la línea de comandos, la opción -datos especifica que el cuerpo de la petición está en perfiles.json.
Observe que sólo el documento de perfil de Ali se envía al punto final del webhook:
En la siguiente sección, configurará un segundo web hook para notificar a todos los usuarios cuando se publique un nuevo artículo que coincida con sus intereses.
Arriba y abajo
Añadir otra entrada webhook que filtre sólo los documentos de tipo artículo:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "manipulador": "webhook", "url": "http://localhost:8000/new_article", "filtro": `función(doc) { si (doc.tipo == "artículo") { devolver verdadero; } devolver falso; }` } |
Añade otro manejador en tu servidor Go:
1 2 3 4 5 6 |
http.HandleFunc("/nuevo_artículo", func(w http.EscritorRespuesta, r *http.Solicitar) { registro.Imprimir("ping") }) |
Compruebe que el webhook funciona como se espera añadiendo un documento de artículo:
1 2 3 4 5 6 |
rizo -H Content-Type: application/json' -vX POST http://localhost:4985/db/_bulk_docs --datos @artículos.json |
NOTA: El contenido de artículos.json se puede encontrar aquí.
En este caso, tienes que hacer un poco más de trabajo para averiguar a qué conjunto de usuarios notificar. Este es un buen caso de uso para utilizar una vista para indexar los documentos de perfil y emitir el tema como clave y los ID de registro como valor para cada tema en la matriz de temas.
Para registrar una vista, podemos utilizar la pasarela de sincronización PUT /_diseño/nombre_del_documento con la definición de la vista en el cuerpo de la solicitud:
1 2 3 4 5 6 |
rizo -H Content-Type: application/json' -vX PUT http://localhost:4985/db/_design/extras --datos @ver.json |
NOTA: El contenido de ver.json se puede encontrar aquí.
Fíjate en que el artículo que publicamos anteriormente tiene diseño como tema y el único usuario suscrito a este tema es Adam. Por lo tanto, si consultas esa vista con la clave "diseño", sólo aparecerá un par (clave, valor) con el tema como clave y los tokens de dispositivo como valor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
rizo -H Content-Type: application/json' -vX GET ':4985/db/_design/extras/_view/user_topics?key="design"' < HTTP/1.1 200 OK < Contenido-Longitud: 95 < Contenido-Tipo: aplicación/json * Servidor Couchbase Sincroniza Pasarela/1.1.0 es no En la lista negra < Servidor: Couchbase Sincroniza Pasarela/1.1.0 < Fecha: Miércoles, 17 Jun 2015 17:46:35 GMT < * Conexión #0 a host intacto {"total_rows":1,"filas":[{"id":"4caa204e81b118cf23500f320e138aa8","llave":"diseño","valor":null}]} |
Ahora, puede editar el controlador en main.go para consultar posteriormente el temas_usuario vista, siendo la clave el tema del artículo:
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 |
http.HandleFunc("/nuevo_artículo", func(w http.EscritorRespuesta, r *http.Solicitar) { registro.Imprimir("ping") var datos mapa[cadena]interfaz{} cuerpo, _ := ioutil.LeerTodo(r.Cuerpo) json.Unmarshal(cuerpo, &datos) tema := datos["tema"].(cadena) registro.Imprimir("Consulta de perfiles de usuario suscritos a %s", tema) var stringUrl cadena = fmt.Sprintf("http://localhost:4985/db/_design/extras/_view/user_topics?key="%s"", tema) res, err := http.Visite(stringUrl) si err != nil { fmt.Imprimir(err) devolver } si res != nil { var resultado mapa[cadena]interfaz{} cuerpo, _ = ioutil.LeerTodo(res.Cuerpo) json.Unmarshal(cuerpo, &resultado) registro.Imprimir("Resultado de la consulta user_topics %v", resultado["filas"].([]interfaz {})) } }) |
Ejecute el documento_granel de nuevo y verá la lista de tokens de dispositivos que se utilizarán en los registros:
Conclusión
En este tutorial, aprendiste a usar Web Hooks en el escenario de GCM Push Notifications y usaste Couchbase Server Views para acceder a información adicional en Webhook Time™ :).
Buen tutorial. Tal vez sea hora de actualizar nuestro código GCM/APNS
Hola,
Gracias por la buena documentación.
¿Hay alguna manera de obtener el archivo adjunto a través de webhook o implementación de plugin, ya que estamos buscando para crear el historial de revisiones del archivo adjunto?
Gracias,
Satinder
Hola Gracias por el tutorial. Me gustaria saber como manejar los borrados. Desde syncgateway sólo proporciona el id, rev y atributos eliminados.
Tengo varios tipos de documentos en un mismo bucket y me interesa sincronizar (es decir, incluir las eliminaciones) sólo un tipo concreto.
Parece que esto debe hacerse en la función de sincronización http://developer.couchbase.com.... Siéntase libre de hacer cualquier pregunta en los foros para entrar en su caso de uso con un poco más de detalle https://forums.couchbase.com/c…
[...] Webhooks, un nuevo mecanismo de integración, proporciona notificaciones de cambio para que puedas integrar fácilmente Couchbase Mobile con aplicaciones de línea de negocio, servicios de terceros, etc. Puedes leer más en el blog del Dev Advocate James Nocentini [...]