Serie de tutoriales para desarrolladores
2025 de mayo
Servicios de caché
Si llevas tiempo desarrollando aplicaciones Vantiq, ya lo sabes. Quizás incluso lo hayas bordado en una almohada o hayas tachado "Vive, ríe, ama" en un tapiz para apoyarlo:
"Actuación
predomina
persistencia."
Queremos decir, por supuesto, que evitar interacciones con bases de datos que consumen muchos recursos aprovechando las funciones de gestión de estado de Vantiq es óptimo para lograr reactividad en tiempo real en los sistemas de aplicaciones. El eslogan no podría interpretarse de otra manera.
Gestión del estado del servicio
Los servicios mantienen el estado necesario para ejecutar la lógica de la aplicación. Se puede establecer un factor de replicación para ese estado para mejorar la tolerancia a fallos. Las tareas de actividad múltiple en los controladores de eventos visuales utilizan el estado del programa, y el servicio genera automáticamente procedimientos que los desarrolladores pueden ejecutar para gestionarlo.
Mitigación de las interacciones de la base de datos
El estado funciona como la memoria de trabajo de la aplicación en ejecución, pero a veces incluso las aplicaciones necesitan buscar información adicional o almacenar información en la base de datos para consultarla posteriormente. Dentro de los Servicios, existen herramientas para minimizar las lecturas y escrituras en la base de datos. Un ejemplo es CachedEnrich, que conserva una operación de lectura de la base de datos en memoria durante un periodo determinado, de modo que las futuras búsquedas en ese periodo utilicen el material en memoria en lugar de iniciar una nueva lectura. Los Procedimientos Programados pueden persistir información en el Estado de forma asíncrona a intervalos de tiempo automatizados. Y, por supuesto, los desarrolladores saben que no es recomendable persistir todos los eventos entrantes. Sea selectivo y conserve solo lo que sea útil para su posterior recuperación.
Servicios en caché
Es hora de presentar otra función que Vantiq ofrece para proteger el rendimiento de las aplicaciones contra interacciones inoportunas o excesivas con la base de datos. Ya lo has visto: cada vez que creas un nuevo servicio, se te pide que selecciones el tipo:

En la clase de Fundamentos, ignoramos (cortésmente, estoy seguro) los Servicios de Caché en favor de la versión "normal", pero resulta que los Servicios de Caché son una herramienta poderosa en el "Minimalismo de Interacción con Bases de Datos". Por lo tanto, merecen atención.
Al hacer clic en la opción "Nuevo servicio de caché", inmediatamente aparecerá otra:

Entonces, hay dos tipos de servicios en caché:
Caché de búsqueda:
Esto es ideal para la información que ya está en una base de datos y que se consultará con frecuencia, pero que no cambia con tanta frecuencia. En otras palabras, se comporta de forma similar a un CachedEnrich.
El tipo seleccionado debe tener una clave de caché única. Esta es una propiedad o conjunto de propiedades únicas que identifican de forma única los registros almacenados en el tipo.
Al abrir el Servicio, verá que ya existe un procedimiento público de servicio generado automáticamente. Curiosamente, no aparece en la lista de "generados". Esto se debe a que se anima a los desarrolladores a realizar cambios en el procedimiento según las necesidades del programa. Una lectura rápida de este código muestra que el procedimiento funciona como se espera:
- Verificar si el registro deseado ya existe en el Estado
- En caso contrario, selecciónelo del tipo y agréguelo al Estado.
- Devolver el registro deseado

Actualizar caché:
Este tipo de servicio de caché funciona como un procedimiento programado, permitiendo al desarrollador configurar la frecuencia de las actualizaciones y desinserciones en un tipo estándar, de forma asíncrona. Como mínimo, el intervalo es por minuto, pero también puede configurarse en semanas.

Al igual que en el caché de búsqueda, el caché de actualización requiere una clave de caché única para realizar escrituras en el tipo.

Cuando se abra el nuevo Servicio, notarás que ya hay tres procedimientos de Servicio escritos para ti:

Vimos el procedimiento “GetBy” del caché de búsqueda, por lo que también puedes usar este servicio como caché de búsqueda.
El procedimiento "UpdateBy" no es lo que se podría pensar. No escribe nada en la base de datos, sino que actualiza el registro de tipo... solo en el estado.
"WriteAll" recopila todos los registros de la partición de estado y realiza una operación de upsert masiva para todos ellos a la vez. Utilizando un modelo de "bloqueo pesimista" (que asume actualizaciones frecuentes de este estado), tras recopilar los registros actuales en la partición de estado, el procedimiento clona la colección y, a partir de entonces, trabaja únicamente con el clon, dejando la partición de estado intacta para que siga cambiando para la siguiente ejecución de WriteAll.
Caso de uso n.° 1: Reemplazar un CachedEnrich con un procedimiento de servicio de caché
¿Recuerda este controlador de eventos visuales de la clase Foundations?

Después de tomar las lecturas del sensor de la bomba, las combinamos por ID de bomba y las enviamos a este VEH. La rama más a la izquierda filtra las lecturas anómalas y agrega la información de la ubicación de la bomba. Detalles de la bomba escribe y envía la mala noticia, donde la trataremos en otro Servicio. Eso Agregar detalles La tarea, justo después del filtro de lecturas incorrectas, es una Enriquecido en cachéEn su lugar, utilizaremos un procedimiento de servicio de caché.
Paso 1: Crear el servicio de caché
En el menú Agregar, seleccione Servicio, luego Nuevo servicio de caché y, finalmente, Servicio de caché. Este será simplemente un servicio de búsqueda:

Paso 2: Ejecutar el procedimiento desde el VEH
Aquí hay un pequeño paso primero. Si lees el Obtener por ID de bomba En el nuevo servicio de caché, observará que la selección ya se realiza mediante el PumpId. Esto significa que no necesitamos usar la tarea SplitByGroup en sentido ascendente. Eliminaremos esta rama y crearemos una nueva para comenzar desde el flujo de eventos, como se muestra a continuación:

Ahora la rama en la que trabajamos se ha movido al centro. Añadamos nuestra nueva tarea "Procedimiento" al filtro:

…y configúrelo con el procedimiento "GetBy..." en PumpDetailsCache. Asegúrese de establecer el parámetro en "event.PumpId". Para que esta tarea de procedimiento se comporte igual que la Agregar detalles Tarea CachedEnrich, configure el Comportamiento de retorno a Adjuntar valor de retorno a returnProperty, y nombra esa propiedad Detalles de la bomba al igual que:

Después de eso, mueva el Búsqueda de direcciones tarea para el Procedimiento tarea, luego elimine la Agregar detalles tarea.

Es hora de ejecutar el nuevo VEH, y está actuando exactamente igual que antes:

¿Pero por qué?
Estupendo, Estás pensando. Reemplazamos un CachedEnrich funcional por un servicio que tuvimos que crear y luego invocar el procedimiento correspondiente. ¿Qué posible ventaja podría aportar esto? Oh, me alegro mucho de que lo preguntes.
Recuerda que al configurar CachedEnrich, debes establecer el intervalo de actualización o dejar el valor predeterminado de una hora. Claro que, si la aplicación lleva 15 minutos ejecutándose y tu compañero actualiza el tipo, los cambios no se verán en la aplicación hasta dentro de 45 minutos. Si reduces el intervalo, es posible que estés añadiendo lecturas innecesarias de la base de datos a la carga. Si hubiera una forma de detectar un cambio en el tipo, borra la caché inmediatamente después.
Ojalá... Ah, espera, sí que lo hay. Volvamos a nuestro servicio en caché y creemos un controlador de eventos para detectar una escritura en el tipo, con lo cual podríamos borrar la caché.
Primero, elegiremos agregar un Controlador de eventos de origen (pestaña Implementar) y lo llamaremos Limpieza al escribir. En la configuración del nuevo flujo de eventos, seleccione tipos como el recurso de entrada, bomba.monitor.DetallesDeLaBomba como inboundResourceId, UPSERT como el op:

…y ahora podemos vincular un procedimiento que borra el caché:

Después de esto, el estado solo se actualizará cuando el tipo de PumpDetails realmente cambie.
Caso de uso n.° 2: escribir el estado del tipo en una base de datos, automáticamente, en intervalos
No hemos terminado con ese VEH del Servicio de análisis, utilizado en el Caso de uso n.° 1. Eso Matriz de estados La tarea era un procedimiento de múltiples particiones que recopilaba todas las lecturas de cada bomba y luego Estado de retención La tarea era una tarea AccumulateState que la mantenía en estado para su uso posterior por parte de nuestro AnalizarInforme Cliente. He decidido que quiero conservar este StateArray en la base de datos... de vez en cuando.
Paso 1: Crear un tipo estándar para almacenar los datos
Actualmente, lo que se incorpora al VEH es un tipo de esquema. Puedes hacer clic en el menú contextual junto a ese tipo en el Contenido del Proyecto y crear un duplicado, solo que esta vez como tipo estándar. El mío lo llamé "PumpStateType".
Paso 2: Crear un servicio en caché basado en el tipo estándar
Esta vez se trata de una caché de actualización. Al principio, establecí el intervalo en una vez por minuto, pero se puede cambiar más adelante. La clave de caché sigue siendo PumpId, que también es un índice único y una clave natural en el tipo.
Paso 3: Verifique la programación “WriteAll…”

Como pueden ver, ya está configurado en un minuto, pero pueden cambiarlo aquí. Lo mantengo así de corto solo para hacer pruebas.
Paso 4: Crear estado para el tipo
He añadido una tarea de procedimiento llamada MakeTypeState a la parte superior Flujo de estado de la bomba Flujo de eventos. Está configurado para llamar al procedimiento "UpdateBy..." en mi servicio de caché para este tipo. Los parámetros son PumpId para la clave, event para el parámetro "event" y false para isPartial.

Después de 10 eventos, hice una búsqueda de registros en PumpStateType:

…esperé un minuto y me refresqué:

El procedimiento programado en el Servicio de caché para el tipo está funcionando perfectamente.
Conclusión:
Existen muchas ventajas al contar con servicios dedicados a mantener el estado y las operaciones de los tipos estándar, como los servicios en caché. Una de ellas es la organización: servicios para tipos, servicios para fuentes, servicios para el procesamiento de eventos, servicios para agentes de IA, etc. Un lugar para cada cosa, y cada cosa en su lugar. Las pruebas para cada servicio son mucho más sencillas si el propósito y las funciones también están claramente definidos. Monitorear lo que hace un sistema de aplicación es mucho más fácil si todas las operaciones de un tipo se almacenan en el mismo servicio, etc.
Los servicios en caché son herramientas útiles para mantener los sistemas de aplicaciones legibles, comprobables, escalables y de alto rendimiento.
Archivos adjuntos:
Debes estar
conectado para ver los archivos adjuntos.
Serie de tutoriales para desarrolladores
2025 de mayo
Servicios de caché
Si llevas tiempo desarrollando aplicaciones Vantiq, ya lo sabes. Quizás incluso lo hayas bordado en una almohada o hayas tachado "Vive, ríe, ama" en un tapiz para apoyarlo:
Queremos decir, por supuesto, que evitar interacciones con bases de datos que consumen muchos recursos aprovechando las funciones de gestión de estado de Vantiq es óptimo para lograr reactividad en tiempo real en los sistemas de aplicaciones. El eslogan no podría interpretarse de otra manera.
Gestión del estado del servicio
Los servicios mantienen el estado necesario para ejecutar la lógica de la aplicación. Se puede establecer un factor de replicación para ese estado para mejorar la tolerancia a fallos. Las tareas de actividad múltiple en los controladores de eventos visuales utilizan el estado del programa, y el servicio genera automáticamente procedimientos que los desarrolladores pueden ejecutar para gestionarlo.
Mitigación de las interacciones de la base de datos
El estado funciona como la memoria de trabajo de la aplicación en ejecución, pero a veces incluso las aplicaciones necesitan buscar información adicional o almacenar información en la base de datos para consultarla posteriormente. Dentro de los Servicios, existen herramientas para minimizar las lecturas y escrituras en la base de datos. Un ejemplo es CachedEnrich, que conserva una operación de lectura de la base de datos en memoria durante un periodo determinado, de modo que las futuras búsquedas en ese periodo utilicen el material en memoria en lugar de iniciar una nueva lectura. Los Procedimientos Programados pueden persistir información en el Estado de forma asíncrona a intervalos de tiempo automatizados. Y, por supuesto, los desarrolladores saben que no es recomendable persistir todos los eventos entrantes. Sea selectivo y conserve solo lo que sea útil para su posterior recuperación.
Servicios en caché
Es hora de presentar otra función que Vantiq ofrece para proteger el rendimiento de las aplicaciones contra interacciones inoportunas o excesivas con la base de datos. Ya lo has visto: cada vez que creas un nuevo servicio, se te pide que selecciones el tipo:
En la clase de Fundamentos, ignoramos (cortésmente, estoy seguro) los Servicios de Caché en favor de la versión "normal", pero resulta que los Servicios de Caché son una herramienta poderosa en el "Minimalismo de Interacción con Bases de Datos". Por lo tanto, merecen atención.
Al hacer clic en la opción "Nuevo servicio de caché", inmediatamente aparecerá otra:
Entonces, hay dos tipos de servicios en caché:
Caché de búsqueda:
Esto es ideal para la información que ya está en una base de datos y que se consultará con frecuencia, pero que no cambia con tanta frecuencia. En otras palabras, se comporta de forma similar a un CachedEnrich.
El tipo seleccionado debe tener una clave de caché única. Esta es una propiedad o conjunto de propiedades únicas que identifican de forma única los registros almacenados en el tipo.
Al abrir el Servicio, verá que ya existe un procedimiento público de servicio generado automáticamente. Curiosamente, no aparece en la lista de "generados". Esto se debe a que se anima a los desarrolladores a realizar cambios en el procedimiento según las necesidades del programa. Una lectura rápida de este código muestra que el procedimiento funciona como se espera:
Actualizar caché:
Este tipo de servicio de caché funciona como un procedimiento programado, permitiendo al desarrollador configurar la frecuencia de las actualizaciones y desinserciones en un tipo estándar, de forma asíncrona. Como mínimo, el intervalo es por minuto, pero también puede configurarse en semanas.
Al igual que en el caché de búsqueda, el caché de actualización requiere una clave de caché única para realizar escrituras en el tipo.
Cuando se abra el nuevo Servicio, notarás que ya hay tres procedimientos de Servicio escritos para ti:
Vimos el procedimiento “GetBy” del caché de búsqueda, por lo que también puedes usar este servicio como caché de búsqueda.
El procedimiento "UpdateBy" no es lo que se podría pensar. No escribe nada en la base de datos, sino que actualiza el registro de tipo... solo en el estado.
"WriteAll" recopila todos los registros de la partición de estado y realiza una operación de upsert masiva para todos ellos a la vez. Utilizando un modelo de "bloqueo pesimista" (que asume actualizaciones frecuentes de este estado), tras recopilar los registros actuales en la partición de estado, el procedimiento clona la colección y, a partir de entonces, trabaja únicamente con el clon, dejando la partición de estado intacta para que siga cambiando para la siguiente ejecución de WriteAll.
Caso de uso n.° 1: Reemplazar un CachedEnrich con un procedimiento de servicio de caché
¿Recuerda este controlador de eventos visuales de la clase Foundations?
Después de tomar las lecturas del sensor de la bomba, las combinamos por ID de bomba y las enviamos a este VEH. La rama más a la izquierda filtra las lecturas anómalas y agrega la información de la ubicación de la bomba. Detalles de la bomba escribe y envía la mala noticia, donde la trataremos en otro Servicio. Eso Agregar detalles La tarea, justo después del filtro de lecturas incorrectas, es una Enriquecido en cachéEn su lugar, utilizaremos un procedimiento de servicio de caché.
Paso 1: Crear el servicio de caché
En el menú Agregar, seleccione Servicio, luego Nuevo servicio de caché y, finalmente, Servicio de caché. Este será simplemente un servicio de búsqueda:
Paso 2: Ejecutar el procedimiento desde el VEH
Aquí hay un pequeño paso primero. Si lees el Obtener por ID de bomba En el nuevo servicio de caché, observará que la selección ya se realiza mediante el PumpId. Esto significa que no necesitamos usar la tarea SplitByGroup en sentido ascendente. Eliminaremos esta rama y crearemos una nueva para comenzar desde el flujo de eventos, como se muestra a continuación:
Ahora la rama en la que trabajamos se ha movido al centro. Añadamos nuestra nueva tarea "Procedimiento" al filtro:
…y configúrelo con el procedimiento "GetBy..." en PumpDetailsCache. Asegúrese de establecer el parámetro en "event.PumpId". Para que esta tarea de procedimiento se comporte igual que la Agregar detalles Tarea CachedEnrich, configure el Comportamiento de retorno a Adjuntar valor de retorno a returnProperty, y nombra esa propiedad Detalles de la bomba al igual que:
Después de eso, mueva el Búsqueda de direcciones tarea para el Procedimiento tarea, luego elimine la Agregar detalles tarea.
Es hora de ejecutar el nuevo VEH, y está actuando exactamente igual que antes:
¿Pero por qué?
Estupendo, Estás pensando. Reemplazamos un CachedEnrich funcional por un servicio que tuvimos que crear y luego invocar el procedimiento correspondiente. ¿Qué posible ventaja podría aportar esto? Oh, me alegro mucho de que lo preguntes.
Recuerda que al configurar CachedEnrich, debes establecer el intervalo de actualización o dejar el valor predeterminado de una hora. Claro que, si la aplicación lleva 15 minutos ejecutándose y tu compañero actualiza el tipo, los cambios no se verán en la aplicación hasta dentro de 45 minutos. Si reduces el intervalo, es posible que estés añadiendo lecturas innecesarias de la base de datos a la carga. Si hubiera una forma de detectar un cambio en el tipo, borra la caché inmediatamente después.
Ojalá... Ah, espera, sí que lo hay. Volvamos a nuestro servicio en caché y creemos un controlador de eventos para detectar una escritura en el tipo, con lo cual podríamos borrar la caché.
Primero, elegiremos agregar un Controlador de eventos de origen (pestaña Implementar) y lo llamaremos Limpieza al escribir. En la configuración del nuevo flujo de eventos, seleccione tipos como el recurso de entrada, bomba.monitor.DetallesDeLaBomba como inboundResourceId, UPSERT como el op:
…y ahora podemos vincular un procedimiento que borra el caché:
Después de esto, el estado solo se actualizará cuando el tipo de PumpDetails realmente cambie.
Caso de uso n.° 2: escribir el estado del tipo en una base de datos, automáticamente, en intervalos
No hemos terminado con ese VEH del Servicio de análisis, utilizado en el Caso de uso n.° 1. Eso Matriz de estados La tarea era un procedimiento de múltiples particiones que recopilaba todas las lecturas de cada bomba y luego Estado de retención La tarea era una tarea AccumulateState que la mantenía en estado para su uso posterior por parte de nuestro AnalizarInforme Cliente. He decidido que quiero conservar este StateArray en la base de datos... de vez en cuando.
Paso 1: Crear un tipo estándar para almacenar los datos
Actualmente, lo que se incorpora al VEH es un tipo de esquema. Puedes hacer clic en el menú contextual junto a ese tipo en el Contenido del Proyecto y crear un duplicado, solo que esta vez como tipo estándar. El mío lo llamé "PumpStateType".
Paso 2: Crear un servicio en caché basado en el tipo estándar
Esta vez se trata de una caché de actualización. Al principio, establecí el intervalo en una vez por minuto, pero se puede cambiar más adelante. La clave de caché sigue siendo PumpId, que también es un índice único y una clave natural en el tipo.
Paso 3: Verifique la programación “WriteAll…”
Como pueden ver, ya está configurado en un minuto, pero pueden cambiarlo aquí. Lo mantengo así de corto solo para hacer pruebas.
Paso 4: Crear estado para el tipo
He añadido una tarea de procedimiento llamada MakeTypeState a la parte superior Flujo de estado de la bomba Flujo de eventos. Está configurado para llamar al procedimiento "UpdateBy..." en mi servicio de caché para este tipo. Los parámetros son PumpId para la clave, event para el parámetro "event" y false para isPartial.
Después de 10 eventos, hice una búsqueda de registros en PumpStateType:
…esperé un minuto y me refresqué:
El procedimiento programado en el Servicio de caché para el tipo está funcionando perfectamente.
Conclusión:
Existen muchas ventajas al contar con servicios dedicados a mantener el estado y las operaciones de los tipos estándar, como los servicios en caché. Una de ellas es la organización: servicios para tipos, servicios para fuentes, servicios para el procesamiento de eventos, servicios para agentes de IA, etc. Un lugar para cada cosa, y cada cosa en su lugar. Las pruebas para cada servicio son mucho más sencillas si el propósito y las funciones también están claramente definidos. Monitorear lo que hace un sistema de aplicación es mucho más fácil si todas las operaciones de un tipo se almacenan en el mismo servicio, etc.
Los servicios en caché son herramientas útiles para mantener los sistemas de aplicaciones legibles, comprobables, escalables y de alto rendimiento.
Archivos adjuntos:
Debes estar conectado para ver los archivos adjuntos.