Eventos

Implementación de un programador a través de eventos Couchbase (Parte 1)

Esta es la primera de una serie de varias partes para aprovechar la Servicio de eventos Couchbase para ejecutar múltiples tareas programadas a intervalos recurrentes específicos en un cron completamente dentro de la base de datos sin necesidad de infraestructura adicional a través de una única función de eventos de uso general.

En esta entrega, nos centraremos en la ejecución de rutinas fijas de usuario, funciones JavaScript definidas dentro de una función de eventos.

En artículos posteriores ampliaremos la cron como Eventing Function para programar y ejecutar sentencias N1QL dinámicas manejadas por la base de datos y finalmente exploraremos la programación de funciones JavaScript dinámicas manejadas por la base de datos.

Fondo

El servicio de eventos de Couchbase proporciona un marco para escribir tus propias rutinas, simples funciones JavaScript, para procesar los cambios en los documentos. Este servicio proporciona toda la infraestructura necesaria para crear funciones escalables y robustas basadas en la nube, permitiéndote centrarte en desarrollar pura lógica de negocio para interactuar casi en tiempo real con los cambios en tus datos. Tus funciones pueden acceder al servicio de datos de Couchbase (KV), al servicio de consultas de Couchbase (N1QL) y a puntos finales REST externos al sistema Couchbase.

Eventing Life Cycle 6.5 I/O

En JSON modelo de datos de Couchbase procede de JavaScriptPor lo tanto, es natural que el servicio de eventos ofrezca la posibilidad de escribir código JavaScript para analizar y manipular documentos JSON en cualquier tipo de evento de cambio, incluyendo inserciones, actualizaciones, fusiones y eliminaciones (denominadas conjuntamente mutaciones).

Las funciones de eventos normalmente le permiten desplegar y ejecutar fragmentos de código personalizados para que reaccionen a miles e incluso millones de mutaciones por segundo en sus documentos. Algunos casos de uso típicos son documentado para desarrollar Funciones Eventing de alta velocidad a escala que respondan a mutaciones de documentos Couchbase.

Eventing Life Cycle 6.5

Este artículo se centrará más bien en un caso de uso de muy baja velocidad del Servicio de Eventos construyendo un crontab distribuido fiable "en base de datos", permitiéndote ejecutar funciones JavaScript que interactúan con servicios Couchbase en un horario periódico regular.

Programación de la lógica empresarial para que se ejecute en una fecha u hora determinadas

Cronque lleva el nombre de "Chronos," la palabra griega para el tiempo es una de las utilidades más útiles en un sistema Linux. En Linux el cron está controlada por un archivo crontab (tabla cron), un archivo de configuración que especifica los comandos del shell que se ejecutarán periódicamente en un horario determinado.

Uno de los inconvenientes cron es que no está diseñado para ser un servicio distribuido; se ejecuta en una sola caja, por lo que presenta un único punto de fallo. Si el sistema está fuera de línea durante varias horas, se pierden todas las tareas programadas.

Sí, hay algunos distribuidos cron como Google's Cloud Service, AWS' Scheduled Tasks, y Azure Functions / Time Triggers. Pero las ofertas de cada proveedor de nube tienen sus propios modismos que no son directamente portables.

Además, es necesario asegurar la metodología de configuración y control, por ejemplo si se controla una cron a través de una API REST sobre HTTP/S, deberá tenerlo en cuenta en su plan de seguridad.

Utilizar el propio Couchbase para ejecutar comandos periódicos

Con una pequeña cantidad de código y planificación, puede aprovechar el servicio Eventing de Couchbase para proporcionar cron para las operaciones o el mantenimiento programados de la base de datos. La integración del programador en la base de datos permite obtener las siguientes ventajas:

  • Portabilidad a través de proveedores Cloud, si reubicas tu cluster de Couchbase tu planificador no se ve afectado.
  • Soporte, si utiliza Couchbase tiene un único proveedor para proporcionarle soporte y otros servicios.
  • Distribuido, no hay un único punto de fallo y todos los servicios de Couchbase admiten réplicas distribuidas.
  • Ejecución garantizada, su tarea se ejecuta incluso después de recuperarse de un fallo de nodo.

Programación de Couchbase, los temporizadores son la salsa secreta

Los temporizadores son construcciones del servicio de eventos de Couchbase mediante las cuales los desarrolladores pueden especificar una rutina (lógica de negocio) que se activará en un momento futuro. Utilizaremos esta funcionalidad para implementar un Couchbase configurable puro. crontab que le permite activar tareas repetitivas como parte de sus flujos de trabajo, tanto si necesita ejecutar una simple consulta N1QL como construir un complejo motor de reglas.

En todos los diseños posteriores limitaremos nuestra cron a una resolución de 15 segundos o más. Tenemos esta limitación porque, aunque los temporizadores se escalan a millones y se garantiza que se disparan y ejecutan, no son precisos como un reloj de pared y actualmente tienen un retardo de estado estacionario limitado a menos de 14 segundos. [1].

Por supuesto, si necesita una programación más ajustada, es decir, menos de 15 segundos, entonces simplemente debe procesar la mutación en sí en la lógica de eventos sin el uso de una construcción de temporizador para programar una llamada de vuelta en el futuro.

En el momento de escribir estas líneas, la versión actual de Couchbase es la 6.5.1 que dos limitaciones con las que debemos trabajar al hacer un robusto cron sistema.

  1. En las versiones 5.5.x, 6.0.x y 6.5.x, una función invocada por una llamada de retorno de un temporizador no puede crear un nuevo temporizador de forma fiable (se puede solucionar mediante una segunda función cooperativa).
  2. En las versiones 6.5.x, la creación de temporizadores en el futuro (como en una hora o más) en un sistema por lo demás inactivo puede dar lugar a un número creciente de operaciones de cubo de metadatos que eventualmente pueden bloquear las mutaciones para una función de Eventing dada (en 6.5.X se puede lograr una solución en el espacio de usuario a través de una segunda función cooperativa). La gravedad se rige por:
    • El número de vBuckets que mantienen un temporizador activo. Por lo tanto, si solo hay unos pocos temporizadores en el futuro, es posible que el problema no se note o no se materialice.  Este es el caso con sólo unos pocos cron horarios, pero para completar en caso de añadir la funcionalidad de la fecha puse en una solución para este problema para el código suministrado en este artículo.
    • Si un temporizador de Eventing se ha disparado recientemente en un vBucket (lo que soluciona el problema para el vBucket en cuestión por función). Por lo tanto, los sistemas con mucha actividad de temporizadores a corto plazo no experimentarán este problema aunque los temporizadores estén programados para un futuro lejano.

Afortunadamente, en la versión 6.6.0 ambos problemas o restricciones se han eliminado y se puede crear un programador en una única y sencilla Función de Eventos unificada.

Eventing cron update

Requisitos previos

En este artículo utilizaremos la última versión de GA, es decir, la versión 6.5.1 de Couchbase (puede que tengas que hacer algunos cambios en las funciones de eventos descritas para versiones anteriores de Couchbase). El ejemplo de este artículo se ejecutará contra el conjunto de datos travel-sample que se entrega con el servidor Couchbase.

CONSEJO PROFESIONAL: Sólo para usuarios avanzados, si estás familiarizado con Couchbase Eventing y también con nuestras herramientas CLI / REST puedes saltarte la mayor parte de este blog y descargar un archivo ZIP para configurar y ejecutar rápidamente el sistema programador que se presenta a continuación. Haz clic con el botón derecho en el siguiente enlace y selecciona Guardar enlace como para descargar el archivo  cron_impl_2func_CLI.zip, muévalo a un nodo Eventing, extraiga el archivo ZIP y consulte el archivo README.txt extraído.

Sin embargo, si usted no está familiarizado con Couchbase o el servicio Eventing por favor camine a través de GET STARTED y un ejemplo Eventing específicamente se refieren a los siguientes:

  • Configure un servidor Couchbase 6.5.1 que funcione según las instrucciones de Comience aquí
  • Asegúrese de que puede ejecutar una consulta N1QL en la base de datos viaje-muestra según las instrucciones de Ejecute su primera consulta N1QL.
  • Comprender cómo desplegar una función básica de Eventing según las instrucciones de la sección Archivo de documentos que también utiliza viaje-muestra conjunto de datos.
  • Asegúrese de tener la viaje-muestra en la vista de cubos de la interfaz de usuario.
  • Asegúrese de que un cubo llamado metadatos en la vista Buckets de la interfaz de usuario debe tener un tamaño mínimo de 200 MB.
  • En la vista Buckets de la interfaz de usuario, cree un bucket llamado crondata con un tamaño mínimo de 200 MB. Para obtener información detallada sobre cómo crear cubos, consulte Crear un cubo.
  • Establecer allow_interbucket_recursion a verdadero para permitir que dos (2) funciones de Eventing modifiquen el mismo documento KV [2].

Implementación #1, programación tipo "cron" codificada.

Para nuestra primera implementación, por ejemplo la Parte 1 de la serie, diseñaremos una estructura de control simple que es simplemente un documento KV JSON y también dos (2) Funciones Eventing que responderán y actuarán sobre la información en la estructura de control.

A continuación se muestra un diseño de un documento JSON, o estructura de control, que nos permitirá tener múltiples "eventos" programados. Cada evento programado tendrá su propio documento de control con una CLAVE única como recurring_event::1, recurring_event::1, ... recurring_event::N. La propia estructura JSON contiene información para "reconstituir la clave", ya que nuestro sistema de programación responderá a los cambios o actualizaciones (mutaciones) de los documentos de control, como alternar el estado "activo" para activar o desactivar la acción o cambiar el campo "verbose" que controla la cantidad y el estilo del registro.

A continuación se muestra un ejemplo de documento de control con CLAVE evento_recurrente::1 que ejecutará la función JavaScript doCronActionA a las 14:54 (14:30) todos los días.

Registro de control JSON Descripción
{
   "type": "recurring_event", La CLAVE será <>::<>.
   "id":1,
   "hora":14, La hora del día 0-23, *, *2X, *4X para activar
   "min":54, El minuto en la hora 0-59, *, *2X, *4X para activar
   "acción": "doCronActionA", Función JavaScript que se ejecutará cuando se active el temporizador
   "activo":true, Bandera para activar o desactivar este horario
   "verbose": { [OPCIONAL] control de registro
      "user_func":2, Nivel de registro para la lógica de acción : 0=ninguno, etc. etc.
      "programador":3 Nivel de registro para la lógica cron : 0=ninguno, etc. etc.
   },
   "dinámico": { control y estadísticas del sistema [DINÁMICO
      "estado": "brazo", "armar"|"rearmar"|"pendiente" cualquier valor != "pendiente" iniciar una programación
      "next_sched": 0, Número de segundos transcurridos desde la época hasta el siguiente horario deseado
      "prev_sched": 0, Número de segundos transcurridos desde la fecha de la programación anterior
      "prev_etime": 0, Número de segundos transcurridos desde la época para el tiempo de ejecución real del programa anterior
      "prev_delay": 0, Número de segundos que el temporizador se ha retrasado con respecto a la programación
      "prev_atime": 0 Número de segundos que ha tardado el usuario 'acción'
   }
}

Como Linux tradicional crontab puede establecer la hora y el minuto en números enteros legales, y también puede establecer hora a "*" para procesar todas las horas o ajuste min a "*" para procesar todos los minutos.

Aunque no apoyaremos la crontab sintaxis admitimos dos configuraciones no estándar, a saber, si fijar ambos hora y min a "*4X" ejecutaremos y rearmaremos cuatro (4) veces por minuto y si los configuras ambos a "*2X" ejecutaremos y rearmaremos dos (2) veces por minuto. A continuación se muestra una tabla de horarios soportados con su descripción:

hora min Los valores pueden ser números o cadenas
13 32 Corre a las 13:32 (o 13:32)
* 15 Se ejecuta cada hora a los 15 minutos
8 12 Corre una vez al día a las 8:32 (o 8:32 am)
* * Ejecutar una vez por minuto
*2X *2X Se ejecuta dos veces por minuto - requiere que tanto la hora como el minuto estén ajustados a "*2X".
*4X *4X Funciona cuatro veces por minuto - requiere que la hora y el minuto estén ajustados a "*2X".

Eventualmente utilizaremos el Query Workbench para insertar el cron documentos de control, todos los cuales deben tener una CLAVE única de evento_recurrente::# a una hora de ejecución programada de 14:54 ( 2:54 pm), para la acción doCronActionA, podríamos utilizar la siguiente sentencia N1QL.

No te preocupes por ejecutar ninguna sentencia N1QL en este momento, realizaremos las sentencias N1QL más tarde después de haber construido y desplegado nuestra Función de Eventos.

Puede crear un registro (o registros) de control en el cubo viaje-muestray luego listarlo, armarlo, desarmarlo, ajustar el horario que sigue, cambiar el nivel de verbosidad para el registro, o borrarlo de la siguiente manera:

Acción Declaración N1QL
Crear un calendario INSERTAR EN viaje-muestra (CLAVE,VALOR) VALORES (
"recurring_event::1", {
"type": "recurring_event",
"id":1,
"hora": "14″,
"min": "54″,
"acción": "doCronActionA",
"activo":true
}
);
Crear un índice para consultar datos sin especificar claves CREAR un índice primario sobre crondata ;
Mostrar todos los horarios ordenados por id SELECT * FROM crondata WHERE type="recurring_event" order by id ;
Mostrar horario específico SELECT * FROM crondata WHERE type="recurring_event" AND id=1 ;
Armar o activar ACTUALIZACIÓN crondata SET active = true WHERE type="recurring_event" AND id=1 ;
Desarmar o desactivar ACTUALIZACIÓN crondata SET active = false WHERE type="recurring_event" AND id=1 ;
Ajustar el tiempo de activación ACTUALIZACIÓN crondata SET hora = 11, min = 30 WHERE type="recurring_event" AND id=1 ;
Ajustar el registro de la "acción ACTUALIZACIÓN crondata SET verbose.user_data = 0 WHERE type="recurring_event" AND id=1 ;
Ajustar el registro de la lógica del programador ACTUALIZACIÓN crondata SET verbose.scheduler = 0 WHERE type="recurring_event" AND id=1 ;
Borrar el horario DELETE FROM crondata WHERE type="recurring_event" AND id=1 ;

Supongamos que tenemos cuatro (4) horarios activos, la ejecución de la primera sentencia N1QL, por encima de la lista de todos ellos, por ejemplo.

Devolvería algo como la siguiente salida (vista de tabla en el Query Workbench):

activo acción hora id min programador tipo usuario_func
verdadero "doCronActionA" 14 1 54 1 "evento_recurrente" 2
verdadero "doCronActionB" * 2 * 1 "evento_recurrente" 1
verdadero "doCronActionC" *2X 3 *2X 4 "evento_recurrente" 4
verdadero "doCronActionD" * 4 0 0 "evento_recurrente" 1

En la tabla anterior tenemos cuatro acciones: la primera se ejecuta una vez al día, la segunda cada minuto, la tercera cada 30 segundos y la cuarta cada hora. En una próxima entrega de esta serie añadiremos la función "día de la semana".

El objeto anidado "verbose"si no se suministra será por defecto { "user_func":1, "scheduler":1 } indicando un nivel de registro bajo o escueto para la función de acción y también para la lógica de programación. Un valor de 0 suprimirá todos los mensajes de registro, es decir, doCronActionD, mientras que valores mayores serán más verbosos, es decir, como se define en doCronActionC.

El objeto anidado "dinámico" si normalmente nunca se suministra y será por defecto { "state": "arm", "next_sched": 0, "prev_sched": 0, "prev_etime": 0, "prev_delay": 0, "prev_atime": 0 } este es un bloc de notas para la programación lógica de eventos en ejecución y también proporciona estadísticas útiles sobre los tiempos de ejecución, por lo que debe ser tratado como de sólo lectura.

En este punto tenemos un diseño de control de alto nivel, pero necesitamos lógica para procesar nuestras estructuras de control, aquí es donde el Servicio de Eventos de Couchbase, específicamente una Función de Eventos entra en juego.

Funciones del concurso

Este diseño requiere dos (2) funciones de Eventing: una función JavaScript principal "cron_impl_2func_651" y una pequeña función JavaScript de ayuda "cron_impl_2func_651_help". Discutiremos cada sección de las funciones JavaScript que comprende la implementación inicial combinada de código JavaScript de casi 610 líneas (con aproximadamente 44% de las líneas son comentarios y espacios en blanco)

No te preocupes por hacer un cortar y pegar en este momentoComo más tarde voy a proporcionar un enlace para descargar (para la importación) las dos funciones de eventos necesarios y todos los ajustes necesarios en dos archivos llamados "cron_impl_2func_651.json" "cron_impl_2func_651_help.json" y también si lo prefiere las dos funciones unificadas completo que se puede cortar y pegar directamente.

Nuestra función principal de eventos "cron_impl_2func_651" estará compuesta por nueve (9) funciones JavaScript

  • Tres (3) funciones de lógica empresarial (dos de las cuales están vacías).
    • doCronActionA(doc) - una acción de usuario de ejemplo N1QL a ejecutar
    • doCronActionB(doc) - un intérprete de comandos de acción de usuario vacío para experimentos
    • doCronActionC(doc) - un intérprete de comandos de acción de usuario vacío para experimentos
  • Un (1) punto de entrada para concursos completos.
    • OnUpdate(doc, meta) - el punto de entrada estándar de Eventing para Inserciones o Actualizaciones
  • Uno (1) cron analizador sintáctico para generar la siguiente programación.
    • getNextRecurringDate(hour_str, min_str) - lógica cron para encontrar la siguiente Fecha programada
  • Tres (3) funciones de apoyo para comprobar que la lógica de negocio existe o formatear resultados.
    • verifyFunctionExistsViaEval(curDoc, id) - asegurarse de que tenemos una función que ejecutar
    • toNumericFixed(number, precision) - formatea un flotante a un estilo compacto
    • toLocalISOTime(d) - formatea una fecha a un estilo compacto
  • Una (1) función callback cuando se ejecutan los temporizadores.
    • Callback(doc) - una función de devolución de llamada para temporizadores programados

Nuestra función de ayuda para eventos "cron_impl_2func_651_help" estará compuesta por una (1) función JavaScript

  • Un (1) punto de entrada para concursos completos.
    • OnUpdate(doc, meta) - el punto de entrada estándar de Eventing para Inserciones o Actualizaciones

En las secciones siguientes recorreremos cada una de las funciones JavaScript anteriores.

Necesitamos una función JavaScript, por ejemplo, la lógica de negocio para ejecutar en un horario periódico.

Lo primero que queremos es una rutina o función que contenga nuestra lógica de negocio que ejecutaremos basándonos en nuestras reglas crontab. Llamaremos al método JavaScript doCronActionA(doc)sin embargo, puede llamarse como se quiera, por ejemplo doPeriodicLedgerBalance(doc), los únicos requisitos para nuestras funciones de "acción" que implementan nuestra lógica de negocio programada son los siguientes:

  • Tiene un parámetro: doc, un documento de control como el descrito anteriormente de type="recurring_event".
  • El nombre real de JavaScript coincide con el campo "acción" del documento de control.
  • Devuelve verdadero sobre el éxito y falso sobre el fracaso
  • Utiliza doc.verbose.user_func para controlar el registro si 0 es silencioso, si 1 emite una sola línea, si 2 emite cualquier información de registro que se necesite para depurar la función, etc. etc..

Escribiremos nuestra función doCronActionA(doc)para ejecutar una consulta N1QL incrustada ) para combinar los recuentos de líneas aéreas por país y, a continuación, crear un único documento KV con los datos calculados.

En mi sistema de prueba un pequeño nodo único noMDS (ejecutando todos los servicios de Couchbase) el N1QL anterior tarda unos 20 ms. (para mayor claridad fingir que es supercomplejo tarda 10 segundos en completarse).

La idea aquí es que el documento KV final calculado y resumido pueda ser cargado rápidamente por 100K (o un millón) de mutaciones Eventing por segundo sin la sobrecarga adicional de comunicación con los nodos del servicio de Consulta y de procesar sentencias N1QL en cada mutación.

Debería ser obvio que el objetivo de esta lógica de negocio en particular, doCronActionA(doc)es crear una caché semiestática que se actualice periódicamente según un calendario.

Todo lo que estamos haciendo realmente (y es bastante rápido) es obtener un recuento de aerolíneas por país a partir del conjunto de documentos de la muestra de viajes. A medida que usamos N1QL construimos un documento y eventualmente lo escribimos en KV como un documento resumido. El punto clave a destacar aquí es que no queremos repetir el mismo trabajo para millones de mutaciones cada uno, sobre todo porque algunos cálculos podrían tomar 10 segundos de tiempo de cálculo del servicio de consulta cada vez que iniciamos una consulta N1QL incrustada desde una función Eventing.

A continuación mostramos la función JavaScript que queremos que se ejecute una vez al día (o quizás una vez cada hora, etc.). Observa que el nombre de la función coincide con el nombre del campo de acción de la estructura de control. Para más detalles sobre la terminología de Eventing y las construcciones del lenguaje, consulta los documentos y ejemplos de Couchbase en Servicio de Eventing: Fundamentos.

La función anterior simplemente 1) consulta el cubo de muestras de viajes para extraer datos, en este caso el recuento de aerolíneas para cada país, 2) crea un nuevo documento KV y una nueva clave y lo escribe en el cubo de muestras de viajes para su uso posterior.

Además, como parte de este ejemplo hemos construido un registro que responde a un ajuste numérico de verbosidad que a) registra una sola línea si el documento de control tiene un valor para doc.verbose.user_func == 1 o b) emite más información si el valor de doc.verbose.user_func >= 2.

Se trata de un marco genérico que puede ejecutar una (1) cron acción o incluso mil (1000) de cron acciones. Como tal, he proporcionado dos funciones adicionales "vacías" - como se señaló antes, podrían haber sido nombradas de cualquier manera.

y

Estas funciones doCronActionB y doCronActionC son triviales, ya que simplemente registran información en el registro de la aplicación de eventos de la función de eventos. Consulte Funciones de registro para más detalles. Por supuesto, necesita un documento de control de type="recurring_event" con active=true y una acción como action = "doCronActionB" para habilitarlos y ejecutarlos realmente.

Necesitamos un punto de entrada o manejador de eventos

A partir de la versión 6.5, el servicio de eventos admite dos puntos de entrada o controladores OnUpdate(doc, meta) y OnDelete(meta) sólo nos interesa el OnUpdate(doc,meta) para este ejemplo.

En OnUpdate(doc,meta) es llamado cuando se crea o modifica (muta) cualquier documento del bucket de origen y filtra inmediatamente los documentos que no interesan. [3]

La clave aquí es que el cron en nuestro manejador sólo se preocupa por los documentos que tienen doc.type de "recurring_event y también un doc.active de true. Además, en este ejemplo hemos creado un rastreo para el método cron lógica de mantenimiento que sólo se registra en el registro de la aplicación si el documento de control tiene un valor para doc.verbose >= 3.

Si sólo ejecuta unas pocas programaciones, puede desactivar el trabajo en el espacio de usuario o "arreglo para 6.5.X cubo creciente ops" comentando cuatro líneas de código en el bloque OnUpdate anterior para "cron_impl_2func_651" como sigue:

Necesitamos código para solucionar posibles operaciones de crecimiento de cubos para 6.5.X

A partir de la versión 6.5.X necesitamos un "arreglo para 6.5.X cubo creciente ops"que ocurre en sistemas inactivos con muchos temporizadores programados en el futuro. Este código garantiza que un temporizador de Eventing se ha disparado recientemente en un vBucket (lo que soluciona el problema para el vBucket dado en función de cada función).

 Necesitamos una utilidad para calcular la siguiente hora en el horario

La siguiente función getNextRecurringDate(hour, min) determinará una hora para ejecutar la acción definida como parte de nuestra programación. Esto no es una implementación completa de cronEn lugar de ello, contiene las características estándar clave para ejecutarse una vez al día, una vez por hora y una vez por minuto. También contiene alguna sintaxis no estándar para proporcionar la capacidad de ejecutar dos veces por minuto o cuatro veces por minuto.

Como se ha descrito anteriormente, la función getNextRecurringDate(hora, min) permite lo siguiente (la tabla se duplica a continuación), siendo las dos últimas no estándar.[4]

hora min Los valores pueden ser números o cadenas
13 32 Corre a las 13:32 (o 13:32)
* 15 Se ejecuta cada hora a los 15 minutos
8 12 Corre una vez al día a las 8:32 (o 8:32 am)
* * Ejecutar una vez por minuto
*2X *2X Se ejecuta dos veces por minuto - requiere que tanto la hora como el minuto estén ajustados a "*2X".
*4X *4X Funciona cuatro veces por minuto - requiere que la hora y el minuto estén ajustados a "*2X".

A continuación se muestra una implementación de la lógica necesaria para determinar la próxima vez que debe activarse un temporizador de Eventing en nuestro programa, en el caso de que la lógica de usuario de nuestro primer ejemplo doCronActionA(doc) no se completa a tiempo, por ejemplo, si se sobrepasa el tiempo real, se seleccionará el siguiente cuanto de la programación. Tenga en cuenta tanto los Temporizadores como sus Funciones Padre. Así, si una Función de Eventos tiene un tiempo de espera de ejecución por defecto de 60 segundos, si es necesario esta configuración puede ser ajustada o aumentada.

Necesitamos algunas pequeñas utilidades

La función de utilidad común que simplemente comprueba si nuestro JavaScript existe utilizado por ambos OnUpdate(doc,meta), mostrado arriba, y el temporizador Devolución de llamada(doc), que se muestra más adelante. A continuación verifyFunctionExistsViaEval(curDoc, id) que recibe dos argumentos: un documento de control JSON y la CLAVE de dicho documento.

Esto nos permite saber inmediatamente, en el despliegue, si hubo un problema con una falta de coincidencia de nombres entre el documento de registro de control JSON y el nombre real de la función de lógica de negocio en el código JavaScript.

Tenga en cuenta que si se intenta ejecutar una función inexistente, el usuario final recibirá una advertencia en el registro de la aplicación. cron_impl_2func_651.log  para corregir el problema.

2020-04-22T16:20:38.725-07:00 [INFO] "Advertir/Desactivar (Sin Acción y Sin Rearmar), porque la 'acción' requerida de doCronMyNewFunction(doc) no existe, id es" "recurring_event::1"

Esta corrección se puede hacer a través de una Pausa/Reanudar añadiendo la función y luego ajustando el documento de control con el id especificado o CLAVE (a través de un toggle activo a falso y luego verdadero) -o- ajustando el documento de control para apuntar a una función existente en su manejador.

A continuación, la utilidad toNumericFixed(número, precisión) sólo permite un bonito formato compacto de flotantes para nuestros mensajes de registro.

Por último, la utilidad toLocalISOTime(d) sólo permite un formato compacto de fechas para nuestros mensajes de registro.

Necesitamos una llamada de retorno del temporizador para ejecutar la lógica de usuario y volver a activar el temporizador

La última función JavaScript de "cron_impl_2func_651" es la llamada de retorno del temporizador, a la que se llama cuando se activa el temporizador programado. La función de devolución de llamada debe ser una función de nivel superior que reciba un único argumento, el contexto.

En este caso en nuestro manejador OnUpdate referenciamos una función JavaScript de Devolución de llamada(doc) con un contexto de doc (nuestro documento de control del planificador activo de type="recurring_event")

En la versión 6.6 podemos crear otro temporizador dentro de un temporizador pero para todas las versiones anteriores necesitaremos lanzar una mutación a una función "helper" (evitamos cuidadosamente la recursión infinita). En la 6.6 la función helper no es necesaria y la lógica se ha simplificado sustancialmente.

Necesitamos una función de ayuda para desencadenar una nueva mutación

Dado que antes de la versión 6.6 (que aún no se ha publicado) no se puede crear un temporizador desde la llamada de retorno de un temporizador en ejecución, necesitamos una segunda función de eventos (junto con "allow_interbucket_recursion":true) para activar una mutación de forma que podamos generar todos nuestros temporizadores en el punto de entrada OnUpdate(doc,meta) de la función de eventos principal. Hacemos esto de la siguiente manera:

  1. cron_impl_2func_651 OnUpdate(doc,meta) recibe una mutación, programa un temporizador
  2. cron_impl_2func_651 Después de una cantidad de tiempo cuando el temporizador madura el Devolución de llamada(doc) se ejecuta la rutina, primero ejecuta la acción de usuario deseada y luego crea una mutación #1 en el documento de control (que no es vista por la Función creadora para evitar la recursividad)
  3. cron_impl_2func_651_help OnUpdate(doc,meta) recibe una mutación, hace otra mutación #2 en el documento de control esto desencadena 1. anterior en un ciclo sin fin.

Nota, en la versión 6.6 de Couchbase no necesitamos una función de ayuda en absoluto porque se te permite crear un temporizador desde dentro de un temporizador en ejecución. Esto simplifica enormemente la lógica necesaria para hacer un cron sistema[2].

La única función JavaScript en "cron_impl_2func_651_help" OnUpdate(doc,meta) se muestra a continuación.

La función helper necesita algunas utilidades

Estas utilidades proporcionan un arreglo para 6.5.X cubo creciente ops asegurándose de que se dispara un temporizador de eventos en cada vBucket en el momento oportuno.

Ahora vamos a desplegar las dos Funciones Eventing

Hemos revisado mucho código y el diseño del planificador inicial, ahora es el momento de ver cómo funciona todo junto.

Recuerde que en este ejemplo hay tres cubos muestra-viaje (un ejemplo de conjunto de datos por defecto), metadatos(el cubo de metadatos es un bloc de notas para Eventing y puede compartirse con otras funciones de Eventing) y, por último, la función crondata (que contiene nuestros cronogramas). La dirección viaje-muestra tiene un tamaño de 100 MB y los otros dos cubos metadatos y crondata deben tener un tamaño de 200 MB y existir ya según las instrucciones de "Requisitos previos".

  • Verifique la configuración actual de su cubo accediendo a la página Consola Web de Couchbase > Cubos página:Eventing cron update

Para desplegar la función Eventing "cron_impl_2func_651"puede seguir uno de estos dos métodos:

  • Complejidad básica, Método #1 Descargar/Importar
  • Complejidad media, Método #2 Añadir función manualmente, Cortar y pegar JavaScript

Método #1 Descargar/Importar

Importar la 1ª función "cron_impl_2func_651"

Descargue la primera función Eventing con todos los ajustes necesarios, haga clic con el botón derecho del ratón en el siguiente enlace y seleccione Guardar enlace como para descargar el archivo cron_impl_2func_651.json en tu sistema de archivos local.

Desde el Consola Web de Couchbase > Eventos haga clic en IMPORTARnavega hasta el archivo cron_impl_2func_651.jsonselecciónelo y ábralo. La página AÑADIR FUNCIÓN aparece el cuadro de diálogo.

En el AÑADIR FUNCIÓN para cada uno de los elementos de la función, facilite la siguiente información. Tenga en cuenta el archivo JSON cron_impl_2func_651.json preconfigurará todos los ajustes correctamente para este ejemplo:

  • Para el Cubo de origen y compruebe que está en crondata.
  • Para el Cubo de metadatos y compruebe que está en metadatos.
  • Compruebe que cron_impl_2func_651 es el nombre de la función que está creando en el campo Nombre de la función cuadro de texto.
  • [Paso opcional] Introduzca el texto Un programador cron parte 1en el Descripción cuadro de texto.
  • Para el Ajustes utilice los valores por defecto.
  • Para el Fijaciones verifique que existen dos enlaces.
  • Para la vinculación, el "alias de cubo", especifica cron_bkt como "nombre alias" del cubo, y seleccione
    crondata como cubo asociado, y el modo debe ser "lectura y escritura".
  • Para la vinculación, el "alias de cubo", especifica ts_bkt como "nombre alias" del cubo, y seleccione
    viaje-muestra como cubo asociado, y el modo debe ser "lectura y escritura".
  • La configuración en el cuadro de diálogo debe ser como la siguiente:
    Eventing cron update
  • Después de verificar toda la información requerida en el cuadro de diálogo AÑADIR FUNCIÓN, haga clic en Siguiente: Añadir Código. Aparecerá la página cron_impl_2func_651 (con el código JavaScript precargado).
    Eventing cron update
  • Para volver a la pantalla de Eventos, pulse el botón '< volver a Concurso completo(debajo del editor) o haga clic en el enlace Eventos ficha.

Importar la 2ª Función "cron_impl_2func_651_help"

Descargue la segunda función Eventing con todos los ajustes necesarios, haga clic con el botón derecho del ratón en el siguiente enlace y seleccione Guardar enlace como para descargar el archivo cron_impl_2func_651_help.json en tu sistema de archivos local.

Desde el Consola Web de Couchbase > Eventos haga clic en IMPORTARnavega hasta el archivo cron_impl_2func_651_help.jsonselecciónelo y ábralo. La página AÑADIR FUNCIÓN aparece el cuadro de diálogo.

En el AÑADIR FUNCIÓN para cada uno de los elementos de la función, facilite la siguiente información. Tenga en cuenta el archivo JSON cron_impl_2func_651_help.json preconfigurará todos los ajustes correctamente para este ejemplo:

  • Para el Cubo de origen y compruebe que está en crondata.
  • Para el Cubo de metadatos y compruebe que está en metadatos.
  • Compruebe que cron_impl_2func_651_help es el nombre de la función que está creando en el campo Nombre de la función cuadro de texto.
  • [Paso opcional] Introduzca el texto Un ayudante cron como programador parte 1en el Descripción cuadro de texto.
  • Para el Ajustes utilice los valores por defecto.
  • Para el Fijaciones verifique que sólo existe un enlace.
  • Para la vinculación, el "alias de cubo", especifica cron_bkt como "nombre alias" del cubo, y seleccione
    crondata como cubo asociado, y el modo debe ser "lectura y escritura".
  • La configuración en el cuadro de diálogo debe ser como la siguiente:
    Eventing cron update
  • Después de verificar toda la información requerida en el cuadro de diálogo AÑADIR FUNCIÓN, haga clic en Siguiente: Añadir Código. Aparecerá la página cron_impl_2func_651_help (con el código JavaScript precargado).
    Eventing cron update
  • Para volver a la pantalla de Eventos, pulse el botón '< volver a Concurso completo(debajo del editor) o haga clic en el enlace Eventos ficha.

Método #2 Añadir función manualmente, cortar y pegar JavaScript

Crear manualmente "cron_impl_2func_651"

Para añadir la primera función de Eventing desde Consola Web de Couchbase > Eventos haga clic en AÑADIR FUNCIÓNpara añadir una nueva función. La dirección AÑADIR FUNCIÓN aparece el cuadro de diálogo.

En el AÑADIR FUNCIÓN para cada elemento de la función, facilite la siguiente información:

  • Para el Cubo de origen seleccione crondata.
  • Para el Cubo de metadatos seleccione metadatos.
  • Visite cron_impl_2func_651 es el nombre de la función que está creando en el campo Nombre de la función cuadro de texto.
  • [Paso opcional] Introduzca el texto Un programador cron parte 1en el Descripción cuadro de texto.
  • Para el Ajustes utilice los valores por defecto.
  • Para el Fijaciones crear dos enlaces:
  • Para la vinculación, el "alias de cubo", especifica cron_bkt como "nombre alias" del cubo, y seleccione
    crondata como cubo asociado, y el modo debe ser "lectura y escritura".
  • Para la vinculación, el "alias de cubo", especifica ts_bkt como "nombre alias" del cubo, y seleccione
    viaje-muestra como cubo asociado, y el modo debe ser "lectura y escritura".
  • Una vez configurados los ajustes, el cuadro de diálogo debería tener este aspecto:
    Eventing cron update
  • Tras facilitar toda la información requerida en el AÑADIR FUNCIÓN pulse Siguiente Añadir código. En cron_impl_2func_651 aparece el cuadro de diálogo. La página cron_impl_2func_651 contiene inicialmente un bloque de código. Usted sustituirá su cron_impl_2func_651 en este bloque.Eventing cron update
  • Copie el siguiente código fuente JavaScript de Eventing Function (618 líneas) y péguelo en el bloque de código del marcador de posición de cron_impl_2func_651
  • Después de pegar, aparece la pantalla que se muestra a continuación:Eventing cron update
  • Haga clic en Guardar.
  • Para volver a la pantalla de Eventos, pulse el botón '< volver a Concurso completo(debajo del editor) o haga clic en el enlace Eventos

Crear manualmente "cron_impl_2func_651_help"

Para añadir la segunda función de Eventing desde Consola Web de Couchbase > Eventos haga clic en AÑADIR FUNCIÓNpara añadir una nueva función. La dirección AÑADIR FUNCIÓN aparece el cuadro de diálogo.

En el AÑADIR FUNCIÓN para cada elemento de la función, facilite la siguiente información:

  • Para el Cubo de origen seleccione crondata.
  • Para el Cubo de metadatos seleccione metadatos.
  • Visite cron_impl_2func_651_help es el nombre de la función que está creando en el campo Nombre de la función cuadro de texto.
  • [Paso opcional] Introduzca el texto Un ayudante cron como programador parte 1en el Descripción cuadro de texto.
  • Para el Ajustes utilice los valores por defecto.
  • Para el Fijaciones crear un enlace:
  • Para la vinculación, el "alias de cubo", especifica cron_bkt como "nombre alias" del cubo, y seleccione
    crondata como cubo asociado, y el modo debe ser "lectura y escritura".
  • Una vez configurados los ajustes, el cuadro de diálogo debería tener este aspecto:
    Eventing cron update
  • Tras facilitar toda la información requerida en el AÑADIR FUNCIÓN pulse Siguiente Añadir código. En cron_impl_2func_651_help aparece el cuadro de diálogo. La página cron_impl_2func_651_help contiene inicialmente un bloque de código. Usted sustituirá su cron_impl_2func_651_help en este bloque.Eventing cron update
  • Copie el siguiente código fuente JavaScript de Eventing Function (187 líneas) y péguelo en el bloque de código del marcador de posición de cron_impl_2func_651_help
  • Después de pegar, aparece la pantalla que se muestra a continuación:Eventing cron update
  • Haga clic en Guardar.
  • Para volver a la pantalla de Eventos, pulse el botón '< volver a Concurso completo(debajo del editor) o haga clic en el enlace Eventos

Despliegue de las dos funciones

Ahora estamos listos para iniciar las funciones de Eventing. Desde el Consola Web de Couchbase > Eventos pantalla:

  • Haga clic en el nombre de la función cron_impl_2func_651_help para expandir y exponer los controles de Función.Eventing cron update
  • Haga clic en Despliegue.
  • En el Confirmar función de despliegue seleccione "A partir de ahora" de la opción Límite de alimentación.

Empecemos con la otra función de Eventing. Desde el Consola Web de Couchbase > Eventos pantalla:

  • Haga clic en el nombre de la función cron_impl_2func_651 para expandir y exponer los controles de Función.Eventing cron update
  • Haga clic en Despliegue.
  • En el Confirmar función de despliegue seleccione "A partir de ahora" de la opción Límite de alimentación.

Configurar un cron tarea a ejecutar cuatro (4) veces por minuto

En este punto nuestra función Eventing está esperando una mutación específicamente cualquier documento de type="recurring_event" que tenga un campo active=true.

Desde el Consola Web Couchbase > Consulta utilizaremos N1QL para crear una nueva tarea programada en el cubo "muestra-viaje":

  • Corta y pega la siguiente sentencia N1QL en el archivo Editor de consultas
  • Haga clic en Ejecute
    Eventing cron update

Activar nuestro primer cron tarea

El documento de control que hicimos anteriormente no se activó porque especificamos "active":false, además la programación anterior sólo se ejecutará una vez por hora, pero queremos probar las cosas y ver que funcionen en un futuro próximo.

En primer lugar necesitamos un índice para poder manipular nuestros documentos de control en N1QL esto sólo tiene que hacerse una vez

  • Corta y pega la siguiente sentencia N1QL en el archivo Editor de consultas

Corta y pega la siguiente sentencia N1QL en el archivo Editor de consultasAhora activaremos la tarea, pero ajustaremos el horario de repetición a cada 15 segundos para ver exactamente cómo se comporta el sistema. Para ello modificaremos el documento de control con la CLAVE recurring_event::1

  • Haga clic en Ejecute
    Eventing cron update

Utilizamos la sintaxis no estándar de ="*4X" para programar un elemento recurrente cuatro veces por minuto podemos ver nuestra función de trabajo doCronActionA ejecutándose y también la lógica de mantenimiento para programar la función a través de sentencias de registro porque hemos establecido verbose=3.

El programador se ejecuta ahora cuatro veces por minuto. Puede ver la actividad en las estadísticas y en los archivos de registro de la aplicación para las funciones de eventos. cron_impl_2func_651 y cron_impl_2func_651_help.

  • Acceder a la Consola Web de Couchbase > Panel de control verás una ráfaga de actividad cada 15 segundos:Eventing cron update
  • Acceder a la Consola Web de Couchbase > Eventos y haga clic en el botón Registro enlace del desplegado cron_impl_2func_651 Función de registro de eventos. Este cuadro de diálogo Registro de funciones enumera las sentencias de registro en orden inverso (los elementos más nuevos primero). La salida inicial debería ser similar a la siguiente:
    2020-05-20T18:34:33.340-07:00 [INFO] "OnUpdate B recurring_event::1 temporizador recurrente fue creado, timer_id 570927555481258455388"
    2020-05-20T18:34:33.340-07:00 [INFO] "OnUpdate A recurring_event::1 rcv mutation (initial or rearm) schedule timer at 2020-05-20T18:34:45.000"
    2020-05-20T18:34:33.233-07:00 [INFO]"doCronActionA upsert to KV with KEY cron_cache::airlines_by_country cachedoc " {"type": "cron_cache", "id": "airlines_by_country", "date": "2020-05-21T01:34:33.232Z", "data":{"Estados Unidos":127, "Reino Unido":39, "Francia":21}}
    2020-05-20T18:34:33.233-07:00 [INFO] "Callback R recurring_event::1 action took 0.013 sec., returned true"
    2020-05-20T18:34:33.233-07:00 [INFO] "Callback C recurring_event::1 curDoc" {"action": "doCronActionA", "active":true, "hour": "*4X", "id":1, "min": "*4X", "type": "recurring_event", "verbose":{"scheduler":3, "user_func":2}, "dynamic":{"state": "pending", "next_sched":1590024885, "prev_sched":1590024870, "prev_etime":1590024873, "prev_delay":3.218,”prev_atime”:0.013}}
    2020-05-20T18:34:33.233-07:00 [INFO] "Callback B recurring_event::1 sched 1590024870, actual 1590024873, delay 3.218, took 0.013"
    2020-05-20T18:34:33.233-07:00 [INFO] "Callback A recurring_event::1 gen mutation #1 to doc to force schedule rearm at 2020-05-20T18:34:45.000"
    2020-05-20T18:34:33.232-07:00 [INFO] "doCronActionA N1QL idx 2, country France cnt 21"
    2020-05-20T18:34:33.232-07:00 [INFO] "doCronActionA N1QL idx 1, country Reino Unido cnt 39"
    2020-05-20T18:34:33.232-07:00 [INFO] "doCronActionA N1QL idx 0, country Estados Unidos cnt 127"
    2020-05-20T18:34:33.220-07:00 [INFO] "doCronActionA acción de usuario controlada por recurring_event::1"
    2020-05-20T18:34:19.340-07:00 [INFO] "OnUpdate B recurring_event::1 temporizador recurrente fue creado, timer_id 381384185845112994486"
    2020-05-20T18:34:19.340-07:00 [INFO] "OnUpdate A recurring_event::1 rcv mutation (initial or rearm) schedule timer at 2020-05-20T18:34:30.000"

    La línea más antigua en la parte inferior es la mutación que inició el programa (o rearmó el programa), por ejemplo, el mensaje OnUpdate, y vemos las dos primeras ejecuciones completas de la lógica de negocio que codificamos en doCronActionA

  • También habrá algunos mensajes relacionados con el "arreglo para 6.5.X cubo creciente ops"pero se registrará en cron_impl_2func_651_help verá mensajes como el siguiente cada 30 segundos aproximadamente:
    2020-05-20T18:34::49.185-07:00 [INFO] "seeding one doc to each vBucket in primary_bucket alias (took 221 mililis)"

Vamos a ajustar tanto la frecuencia como la verbosidad de esta tarea concreta. Utilizaremos el estándar cron sintaxis de "*" para ambos hora y min para obtener una programación recurrente de una vez por minuto 4X más lenta que la frecuencia actual. Además, bajaremos el nivel de verbosidad de la lógica del planificador a cero y la función de usuario a 1 para que sólo veamos un mensaje por invocación.

Desde el Consola Web Couchbase > Consulta utilizaremos N1QL para crear una nueva tarea programada en el cubo "muestra-viaje":

  • Corta y pega la siguiente sentencia N1QL en el archivo Editor de consultas
  • Haga clic en Ejecute

Después de un acceso de 2 o 3 minutos el Consola Web de Couchbase > Eventos y haga clic en el botón Registro enlace del desplegado cron_impl_2func_651 Función Eventing.

  • La programación recurrente es ahora de un minuto y mucho menos verbosa. Sólo se emite un mensaje o línea de registro por cada ejecución de función (una vez más en orden temporal inverso).
    2020-05-20T18:43:04.231-07:00 [INFO] "doCronActionA acción de usuario controlada por recurring_event::1"
    2020-05-20T18:42:08.233-07:00 [INFO] "doCronActionA acción de usuario controlada por recurring_event::1"

    Sólo se emite un mensaje o línea de registro por cada ejecución de función de usuario programada, es decir. doCronActionA (de nuevo en orden cronológico inverso).

Veamos el trabajo que se realiza

Este código proporciona un marco práctico para ejecutar cualquier función JavaScript en un horario recurrente y nuestra función doCronActionA es upserting (insertar o actualizar) un documento KV de caché calculado una vez por minuto.

Para comprobar los resultados de la función de eventos desplegada, acceda a la pantalla Consola Web de Couchbase > Cubos y haga clic en el enlace Documentos de la página viaje-muestra cubo.

  • En el cuadro de texto "N1QL DONDE" pasado el siguiente texto.
  • Haga clic en Recuperar documentos
    Ahora debería ver un documento de caché cron_cache::airlines_by_country que se actualiza una vez por minuto mediante la función programada doCronActionA.
    Eventing cron update
  • Haga clic en el identificador "cron_cache::airlines_by_country"verá su documento en caché que está siendo actualizado por la lógica de negocio de doCronActionA.
    Eventing cron update
    Por supuesto, los datos de origen son "estáticos" en este momento, por lo que los recuentos seguirán siendo los mismos.

Veamos el documento de control

Este código proporciona un marco para mantener un poco de estadísticas sobre cada programa en ejecución.

Para comprobar las estadísticas de la función de eventos desplegada, acceda a la pantalla Consola Web de Couchbase > Cubos y haga clic en el enlace Documentos de la página crondata cubo.

  • En el cuadro de texto "N1QL DONDE" pasado el siguiente texto.
  • Haga clic en Recuperar documentos
    Ahora debería ver un documento de su documento de control recurring_event::1 que está controlando la función programada doCronActionA.Eventing cron update
  • Haga clic en el identificador "evento_recurrente::1" verá su documento de control que está siendo actualizado por la lógica del planificador con algunas estadísticas en la dinámica de objetos JSON.
    Eventing cron update
    La parte "dinámica" del documento que se añade automáticamente conserva algunas estadísticas de depuración:
  • prev_sched: es la marca de tiempo UNIX anterior de la última planificación ejecutada
  • prev_etime: es la marca de tiempo UNIX real de la última vez que se ejecutó el programa
  • prev_delay: es el retraso desde el prev_sched hasta el prev_etime
  • prev_atime: es el tiempo que tardó en ejecutarse esta acción, es decir, doCronActionA en ejecutarse.
  • next_sched: es la siguiente ejecución programada para esta acción

Estas estadísticas guardadas en el subobjeto dinámico JSON para cada programación son útiles para determinar que su sistema de programación está en buen estado y que la acción que se está ejecutando está terminando a tiempo.

Comprobar que la caché se actualiza cuando cambian los datos

Todo el propósito de doCronActionA es realizar el trabajo a una hora programada o cerca de ella y actualizar un documento de caché con la CLAVE "cron_cache::airlines_by_country".

Hagamos algunas validaciones en el Query Monitor de que nuestra caché se está actualizando 1) mirando el documento de la caché, 2) eliminando algunas aerolíneas del conjunto de documentos de la muestra de viaje, y 3) verificando que el documento de la caché se actualiza mediante la función doCronActionA.

Desde el Consola Web Couchbase > Consulta utilizaremos N1QL para ver y manipular los datos del cubo "muestra-viaje":

  • Corta y pega la siguiente sentencia N1QL en el archivo
  • Editor de consultas
  • Haga clic en Ejecute
    En la vista JSON del Query Workbench deberías ver:
  • Corta y pega la siguiente sentencia N1QL en el archivo Editor de consultas
  • Haga clic en Ejecute
    En la vista JSON del Query Workbench deberías ver (acabamos de borrar algunos datos)
  • Espere un poco más de un minuto
  • Corta y pega la siguiente sentencia N1QL en el archivo Editor de consultas
  • Haga clic en Ejecute
    En la vista JSON del Query Workbench debería ver que cuatro (4) compañías aéreas ya no están presentes

Iniciar una segunda tarea programada

Este código proporciona un marco práctico para ejecutar de 1 a N funciones JavaScript en horarios recurrentes.

Dejaremos que la función doCronActionA seguirán funcionando en un horario de un minuto, pero ahora habilitaremos doCronActionB en un horario de 30 segundos (dos veces por minuto). Esta función es una shell vacía y sólo registrará que fue invocada.

Desde el Consola Web Couchbase > Consulta utilizaremos N1QL para ver y manipular datos en el directorio 'crondata' cubo:

  • Corta y pega la siguiente sentencia N1QL en el archivo Editor de consultas

  • Haga clic en Ejecute

En este punto está ejecutando dos (2) tareas diferentes cada una en dos (2) horarios diferentes para verificar espere dos o tres minutos e inspeccione los archivos de registro de nuevo

  • Acceder a la Consola Web de Couchbase > Eventos y haga clic en el botón Registro enlace del desplegado cron_impl_2func_651 Función Eventing.
    Sólo se emite un mensaje o línea de registro por cada ejecución de función (una vez más en orden temporal inverso). Vemos que doCronActionA dispara una vez por minuto mientras doCronActionB dispara el doble, por ejemplo, una vez cada 30 segundos.

    2020-05-20T19:16:05.259-07:00 [INFO] "doCronActionA acción de usuario controlada por recurring_event::1"
    2020-05-20T19:16:05.255-07:00 [INFO] "doCronActionB acción de usuario controlada por recurring_event::2"
    2020-05-20T19:15:37.253-07:00 [INFO] "doCronActionB acción de usuario controlada por recurring_event::2"
    2020-05-20T19:15:09.250-07:00 [INFO] "doCronActionA acción de usuario controlada por recurring_event::1"
    2020-05-20T19:15:09.249-07:00 [INFO] "doCronActionB acción de usuario controlada por recurring_event::2"
    2020-05-20T19:14:34.255-07:00 [INFO] "doCronActionB acción de usuario controlada por recurring_event::2"

[OPCIONAL] Pausa / Editar JavaScript / Reanudar

Esencialmente hemos terminado con esta entrega, siéntete libre de experimentar y modificar cosas y experimentar por ejemplo:

Desde el Consola Web de Couchbase > Eventos pantalla:

  • Haga clic en el nombre de la función cron_impl_2func_651 para expandir y exponer los controles de Función.
  • Haga clic en Pausa.
  • En el Confirmar función de pausa seleccione "Función de pausa".
  • Pulse "Editar JavaScript"
  • Si se siente seguro, modifique el doCronActionB para realizar algunas operaciones KV o integrarse con cURL.
    Si sólo quieres ver un cambio añade algo simple a la función prueba algo como lo de abajo:
  • Haga clic en Guardar.
  • Para volver a la pantalla de Eventos, pulse el botón '< volver a Concurso completo(debajo del editor) o haga clic en el enlace Eventos
  • Haga clic en Currículum.
  • En el Confirmar función de reanudación seleccione "Reanudar la función".
  • Espere aproximadamente un minuto y para la función cron_impl_2func_651 desplegar
  • Haga clic en el botón Registro enlace del desplegado cron_impl_2func_651 Función Eventing.
    2020-05-20T19:20:41.343-07:00 [INFO] "esta es mi lógica, a = 1 +7 = 8"
    2020-05-20T19:20:41.343-07:00 [INFO] "doCronActionB acción de usuario controlada por recurring_event::2"

Limpieza

La limpieza consiste en desinstalar y eliminar la función y, a continuación, eliminar los dos buckets creados. Con esto concluye el Ejemplo.

Eliminar funciones

Desde el Consola Web de Couchbase > Eventos pantalla:

  • Haga clic en el nombre de la función cron_impl_2func_651 para expandir y exponer los controles de Función.
  • Haga clic en Despliegue.
  • En el Confirmar Función de Despliegue seleccione "Función Despliegue".
  • Esperar a la función cron_impl_2func_651 para deshacer el despliegue.
  • Haga clic en Borrar.
  • En el Confirmar función de borrado seleccione "Borrar función".

Desde el Consola Web de Couchbase > Eventos pantalla:

  • Haga clic en el nombre de la función cron_impl_2func_651_help para expandir y exponer los controles de Función.
  • Haga clic en Despliegue.
  • En el Confirmar Función de Despliegue seleccione "Función Despliegue".
  • Esperar a la función cron_impl_2func_651_help para deshacer el despliegue.
  • Haga clic en Borrar.
  • En el Confirmar función de borrado seleccione "Borrar función".

Retirar cubos

Siguiente Suelta los cubos 'metadatos' 'crondatayviaje-muestra(siempre se pueden volver a crear).

Desde el Consola Web de Couchbase > Cubos y haga clic en el enlace Documentos de la página viaje-muestra cubo.

  • Haga clic en en el nombre del cubo "metadatos" para expandir y exponer los controles
  • Haga clic en Borrar
  • En el Confirmar Borrar Cubo seleccione "Borrar cubo".
  • Haga clic en en el nombre del cubo "crondata" para expandir y exponer los controles
  • Haga clic en Borrar
  • En el Confirmar Borrar Cubo seleccione "Borrar cubo".
  • Haga clic en en el nombre del cubo "viaje-muestra" para expandir y exponer los controles
  • Haga clic en Borrar
  • En el Confirmar Borrar Cubo seleccione "Borrar cubo".

Reflexiones finales

Espero que hayas encontrado este tutorial educativo y hayas desarrollado una mayor apreciación del Servicio de Eventos Couchbase en su conjunto.

Anteriormente señalé que Eventing está diseñado para procesar mutaciones de alta velocidad (en millones por segundo) desde el flujo DCP del bucket de origen asociado a la función. Esta función de Eventing o planificador sólo necesita reaccionar a cambios mínimos en los documentos del planificador.

He iniciado 5.000 programaciones con este código sin cambios, simplemente añadiendo documentos de control. Incluso he ejecutado 120.000 programaciones cada minuto sólo para probar esta implementación (sí, 120.000 es una cantidad bastante ridícula de programaciones independientes). cron horarios a ejecutar). Además puse 120.000 sc3hedules 2 días en el futuro para asegurarme de que no teníamos problemas de recursos degenerados.

Al verse obligado a utilizar dos Funciones Vespertinas para crear el sistema de programación, la función principal cron_impl_2func_651 y un simple ayudante cron_impl_2func_651_help no era tan elegante como esperaba. Además, tener que trabajar alrededor de una fuga op cubo a través de disparar un temporizador en cada vBucket fue decepcionante por decir lo menos. Afortunadamente, debido a este esfuerzo se implementaron cambios y en la próxima versión 6.6.0 podré hacer un planificador más limpio utilizando una única Evening Function. Las mejoras clave en 6.6 son 1) la capacidad de generar un nuevo temporizador desde dentro de un callback de temporizador y 2) la capacidad de cancelar o sobrescribir un temporizador existente por referencia, y 3) la eliminación del uso creciente de recursos en sistemas inactivos con temporizadores programados en el futuro.

Utilicé un cubo independiente 'crondata' para mantener el horario o los documentos de control (no cuento el uso de 'metadatosya que es un bloc de notas del sistema necesario para Eventing y reservado para Eventing en sí) para ofrecer la máxima flexibilidad a la hora de manipular datos en otros buckets. Si hubiera colocado los documentos de control en otro bucket, no podría realizar operaciones N1QL en ese bucket (ya que es un bucket de origen para la función Eventing) y me habría limitado únicamente a operaciones KV para manipular datos en el bucket colocado.

Te reto a que pruebes otros casos de uso de cron y también a que pienses en otras formas de aprovechar un servicio de programación:

  • Comprobación de un recuento de elementos en un gran conjunto de datos durante las "horas valle" y realización de una purga incremental.
  • Realización del enriquecimiento programado de documentos a través de N1QL.
  • Recalcular periódicamente las carteras de valores.
  • Gestión de TTL o tiempos de expiración a través de N1QL en un horario recurrente, consulte Cómo gestionar documentos Time-To-Live (TTL) con Couchbase N1QL.
  • Integración con puntos finales REST externos de forma repetida, consulte Uso de cURL con el servicio Eventing: Actualización.
  • Actualizar el JavaScript de cron_impl_2func_651 para añadir un nuevo campo "prev_astatus" al objeto dinámico JSON para guardar el indicador de resultado verdadero/falso devuelto por la acción de usuario ejecutada anteriormente.

Actualizaciones

Este blog se actualizó el 24 de julio de 2020 para añadir una solución para las versiones 6.5.x que tienen un número creciente de operaciones de cubo de metadatos que eventualmente pueden bloquear las mutaciones para una función de Eventing dada al crear temporizadores en el futuro (como en una hora+) en un sistema por lo demás inactivo.

Próximos pasos

En unas semanas "Implementación de un cron portátil robusto como programador a través de Couchbase Eventing (Parte 2)"donde exploraremos la ejecución de una secuencia de sentencias N1QL dinámicas controladas por la base de datos sin necesidad de editar la función de eventos o definir un script de "acción" codificado dentro de la función de eventos.

Recursos

Referencias

Nos encantaría saber qué te han parecido las características de la versión 6.5 y cómo beneficiarán a tu negocio en el futuro. Por favor, comparte tu opinión a través de los comentarios o en el Couchbase foro

Notas a pie de página

[1] La implementación del temporizador en el servicio Eventing está diseñada para manejar grandes cantidades de temporizadores distribuidos en millones a alta velocidad. Un solo nodo Eventing puede manejar más de 100K temporizadores por segundo y la única promesa es ejecutar los temporizadores tan pronto como sea posible, por ejemplo, no hay temporizadores perdidos. Tenga en cuenta que el intervalo de escaneo actual es de siete (7) segundos para recoger los temporizadores que están listos para disparar, por lo que debe esperar algunos retrasos. Para más detalles sobre la programación de temporizadores consulte Temporizadores: Precisión de reloj de pared en la documentación de Couchbase.

[2] Ajustando allow_interbucket_recursion a verdadero estás eliminando las protecciones que se colocaron en el servidor Couchbase para proteger contra la lógica Eventing accidental que puede iniciar bucles recursivos infinitos. No hay nada malo con esto pero es fácil cometer un error cuando se aprovecha la recursividad. En las versiones 6.6 de Couchbase ajustando la lógica Eventing puede ser colapsada de dos (2) Funciones Eventing en una (1) Función Eventing simplificada sin necesidad de ajustar la función allow_interbucket_recursion ajuste.

[3] Existen dos limitaciones importantes. En primer lugar, si un documento se modifica varias veces en poco tiempo, las llamadas pueden unirse en un único evento debido a la deduplicación. En segundo lugar, no es posible discernir entre las operaciones de creación y las de actualización. Para las propuestas de un cron función ninguna de las dos limitaciones presenta un problema.

[4] Por qué no implementé la semántica exacta de crontab, podría haberlo hecho pero la cantidad de código es excesiva - te remito a explorar el https://github.com/kelektiv/node-cron junto con sus dependencias moment y moment-timezone (todos ellos paquetes muy grandes). El getNextRecurringDate(hour_str, min_str) puede no ser tan flexible pero es simple y cubre nuestro caso de uso.

Comparte este artículo
Recibe actualizaciones del blog de Couchbase en tu bandeja de entrada
Este campo es obligatorio.

Autor

Publicado por Jon Strabala, Director Principal de Producto, Couchbase

Jon Strabala es Gerente Principal de Producto, responsable del Servicio de Eventos de Couchbase. Antes de unirse a Couchbase, pasó más de 20 años construyendo productos de software a través de diversos dominios, comenzando con EDA en el sector aeroespacial y luego la transición a la construcción de software empresarial centrado en lo que hoy se conoce como "IoT" y "datos a escala". Jon trabajó para varias pequeñas consultoras de software hasta que finalmente fundó y dirigió su propia empresa. Tiene una amplia experiencia en NoSQL/NewSQL, tanto en la contribución como en la comercialización de nuevas tecnologías como los mapas de bits comprimidos y los almacenes de columnas. Jon es licenciado en ingeniería eléctrica y tiene un máster en ingeniería informática, ambos por la Universidad del Sur de California, y un MBA por la Universidad de California en Irvine.

3 Comentarios

  1. ¡Muy interesado en las actualizaciones 6.6.x para utilizar una sola función! Me encanta esta implementación para un programador tipo cron.

    1. ¡Acabo de darme cuenta de que esto está disponible en GitHub! ¡Voy a echar un vistazo a esto! Recomiendo actualizar esta entrada del blog con el enlace :) ¡Gracias!

      1. Jon Strabala, Director Principal de Producto, Couchbase enero 13, 2021 a 9:25 am

        Hola Alex,

        Pronto actualizaré el "cron-like scheduler" con una versión 6.6.0 y una versión 6.6.1 (utilizando accesores de cubo avanzados).

        Sin embargo, lo más probable es que en un blog de seguimiento (Parte 2) - pero voy de enlace cruzado ellos, contento de haber encontrado mi 6.6.0 prototipo en GitHub.

Deja un comentario

¿Listo para empezar con Couchbase Capella?

Empezar a construir

Consulte nuestro portal para desarrolladores para explorar NoSQL, buscar recursos y empezar con tutoriales.

Utilizar Capella gratis

Ponte manos a la obra con Couchbase en unos pocos clics. Capella DBaaS es la forma más fácil y rápida de empezar.

Póngase en contacto

¿Quieres saber más sobre las ofertas de Couchbase? Permítanos ayudarle.