Visión general
El Sistema de Eventos (Event System) es lo que eleva a ProDex de un simulador de flujo de procesos a un sistema capaz de modelar lógica operativa sofisticada. Se construye sobre cuatro primitivas:- Temas (Topics): mensajería pub/sub entre componentes
- Variables de estado (State Variables): estado mutable en tiempo de ejecución que vive en el modelo
- Ganchos de evento (Event Hooks): acciones que se disparan en los eventos del ciclo de vida del propio componente
- Oyentes de evento (Event Listeners): acciones que se disparan cuando se emite un tema suscrito
Temas
Un Tema es un canal nombrado al que los componentes pueden publicar y suscribirse. Cuando un componente publica en un tema, cada componente que tenga un Event Listener suscrito a ese tema reacciona. Los Temas permiten coordinación que no puede expresarse solo a través de conexiones de flujo: un componente puede disparar comportamiento en otro sin estar conectado directamente. Crea y renombra Temas en la pestaña Topics del modal Lookups. Una vez que un Tema existe, los componentes publican en él mediante una acciónemit y se suscriben añadiendo un Event Listener cuyo campo topic lo referencia.
Ejemplo, señal kanban: cuando un búfer (Buffer) downstream cae por debajo de un umbral, un event hook emite el tema replenish. Una Fuente (Source) upstream tiene un Event Listener suscrito a replenish que ejecuta una acción release, generando más material.
Variables de estado
Una Variable de estado es un valor mutable y nombrado que vive en el modelo (no en ninguna entidad individual). Las variables de estado persisten a través de las entidades: retienen su valor a medida que las entidades fluyen por el modelo, y pueden leerse desde cualquier expresión. Usa variables de estado para cualquier cosa que represente el estado del sistema en lugar del estado de una sola entidad: turno actual, contadores de tiempo de actividad de máquinas, niveles de inventario, señales de demanda, promedios móviles. Define Variables de estado en la pestaña State Variables del modal Lookups. Cada una tiene un nombre, untype (uno de number, text, boolean) y un initial_value obligatorio que coincida con el tipo declarado. Una vez definidas, léelas por nombre desde cualquier expresión y escríbelas con una acción assign en cualquier Event Hook, Event Listener o acción programada.
Variables de estado vs. atributos de entidad
- Atributo de entidad: pertenece a una entidad específica y se mueve con ella a través del flujo. Se define en el tipo de entidad.
- Variable de estado: pertenece al modelo y persiste independientemente de las entidades. Se define a nivel del modelo a través del modal Lookups.
Event Hooks
Un Event Hook es una regla en un componente que dispara acciones cuando ocurre uno de los eventos del ciclo de vida de ese mismo componente. Los hooks viven en la sección Event Hooks del panel de configuración de cada componente de flujo: elige el evento de un desplegable, opcionalmente añade una condición y configura una o más acciones.Eventos canónicos por componente
Cada evento solo es válido en tipos de componentes específicos y ejecuta sus expresiones en un contexto específico. Las etiquetas de la UI eliminan el prefijoon_ y usan espacios: entity created en la UI corresponde a on_entity_created en el esquema.
Algunas cosas a notar:
entity entered/entity exitedsolo se disparan en Buffer y Station. Los Procesos no los emiten: usaprocess started/process completed. Los Routers no los emiten: usaentity routed.slot freed/slot workingson de Recursos (Resource), no de Estaciones. La denominación es inusual:slot workingse dispara cuando un slot pasa de FREE a asignado.batch createdes un evento del Separator en contexto multi-entidad sobre las salidas. El evento paralelo del Combiner esbatch assembled, también multi-entidad pero sobre las entradas.- El filtro
entity_typesolo es válido enon_entity_consumeddel Combiner yon_entity_createddel Separator. Otros event hooks se disparan para cada entidad independientemente del tipo.
El orden de ejecución de los hooks no está definido cuando múltiples hooks se disparan en el mismo evento. Si dos hooks en el mismo componente se suscriben al mismo evento, el orden en que se ejecutan no está especificado: no te bases en que los efectos secundarios de uno se vuelvan visibles para el otro dentro de un solo evento.
Tipos de acción
Cuando un hook se dispara, ejecuta una o más acciones. El desplegable Action ofrece (etiquetas de UI en código, nombres de esquema entre paréntesis):assign: escribir en una variable de estado. Ejemplo:assign(CURRENT_SHIFT, "night")oassign(WIP_COUNT, WIP_COUNT + 1).emit: publicar un mensaje en un tema. Ejemplo:emit("replenish").pause: pausar un componente (deja de aceptar y procesar).resume: reanudar un componente pausado.release(release_entity): liberar una entidad a demanda. Válido en Fuentes (libera una nueva entidad) y Búferes (libera la siguiente entidad encolada de un búfer en modo de pausa o retención).set capacity(set_capacity): cambiar la capacidad de un Recurso en tiempo de ejecución.
Restricciones de acción por componente
No todas las acciones son válidas en todos los componentes:
En resumen:
set capacity solo es válido en Resource. release / pause / resume solo son válidos en Source y Buffer. assign y emit son válidos en todas partes.
Condiciones
Cada event hook tiene un campocondition opcional: una expresión booleana del DSL que se evalúa cada vez que se dispara el evento. Si es falsa, se omite la lista de acciones. La condición se ejecuta en el mismo contexto que las acciones (entidad-única para hooks vinculados a entidad, sin-entidad para hooks de slot de recurso, multi-entidad para hooks de lote).
Las condiciones viven a nivel de hook, no de acción: las acciones de un hook se ejecutan todas o se omiten todas.
Event Listeners
Un Event Listener es una regla en un componente que dispara acciones cuando se emite un tema suscrito, desacoplado de cualquier evento del ciclo de vida. Los oyentes viven en la sección Event Listeners del panel de configuración de cada componente de flujo: un hermano de los Event Hooks, con su propio botón Add Listener. Cada oyente tiene:topic(obligatorio): el nombre de un tema declaradocondition(opcional): expresión booleana del DSLactions[]: los mismos seis tipos de acción que los Event Hooks, con las mismas restricciones por componente
Los Event Listeners siempre se ejecutan en contexto sin-entidad, independientemente del componente anfitrión. Un oyente en una Source no puede referenciar atributos de entidad, aunque el hook
on_entity_created de una Source sí pueda. Los oyentes son reacciones a señales a nivel de modelo, no a entidades específicas: no hay ninguna entidad en alcance a menos que una acción la traiga explícitamente (por ejemplo, release).Hooks vs. Listeners
Las dos primitivas de reacción se ven similares pero se comportan de manera diferente:Las suscripciones son estáticas
Las suscripciones se declaran en tiempo de construcción del modelo y nunca cambian en tiempo de ejecución. No hay acciónsubscribe ni unsubscribe. Si necesitas que diferentes oyentes estén activos bajo diferentes condiciones, contrólalo con el campo condition del oyente.
ModelNode y el Sistema de Eventos
Los Nodos de modelo (Model Nodes) pueden hospedar Event Listeners pero no Event Hooks de ciclo de vida: el esquema acepta un arregloevent_hooks[] en un ModelNode, pero no hay eventos canónicos de ciclo de vida definidos para ModelNodes, por lo que cualquier hook autorizado fallaría la validación. Los oyentes (basados en tema) funcionan completamente y son la herramienta correcta para coordinación a nivel de ModelNode.
Validación de loop-back
ProDex previene tres patrones específicos descontrolados:- Bucles directos propios: el hook
on_entity_createdde una Source no puede ejecutar una acciónrelease; el hookon_entity_exitedde un Buffer no puede ejecutar una acciónrelease. Estas dos combinaciones específicas están prohibidas por el validador. - Aciclicidad del grafo de temas: el grafo dirigido de emisiones de temas (donde existe una arista del tema A al tema B cuando un oyente de A emite B) debe ser acíclico. Los ciclos se capturan en la validación, antes de que se ejecute el simulador.
- Los ciclos del grafo de flujo están explícitamente permitidos. Enrutar entidades de vuelta a través de un Proceso upstream (bucles de retrabajo) es un modelo válido: el validador solo marca bucles dirigidos por eventos, no ciclos del grafo de conexiones.
Acciones programadas
Un Calendario (Schedule) también puede disparar acciones en momentos específicos de la simulación, independientemente de cualquier evento del ciclo de vida del componente. Las acciones programadas son más restringidas que las acciones de Event Hook:- Solo
assignyemitson válidas como acciones programadas. - Las acciones vinculadas a componente (
pause,resume,set capacity,release) no están disponibles en calendarios. Usa unemitprogramado a un tema, luego conecta un Event Listener que escuche ese tema y realice la acción vinculada al componente.
Patrones comunes
Kanban / Producción por demanda. Los componentes downstream señalan a las fuentes upstream cuando necesitan más material. Combina una variable de estado (WIP actual) con un Event Hook que emite a un tema cuando WIP cae por debajo de un umbral, más un Event Listener en la Source que escucha el tema y ejecuta una acciónrelease.
Contrapresión. Cuando un búfer downstream está lleno, pausa o ralentiza las llegadas upstream. Un Event Hook observa los cambios de nivel del búfer y actualiza una variable de estado que lee la expresión de tasa de llegada de la Source.
Cambios de capacidad por turno. Los Recursos cambian de capacidad por hora del día. Un emit programado en un tema shift_start_night se dispara en el límite del turno; un Event Listener en el Recurso escucha ese tema y ejecuta set capacity con el valor de la noche.
Coordinación entre componentes. Dos componentes distantes que no están conectados por flujo aún pueden coordinarse a través de un tema compartido. Uno publica, el otro reacciona vía un Event Listener.
Cuándo recurrir al Sistema de Eventos
La mayoría de los modelos simples no necesitan eventos: una Source, unos cuantos Procesos, un Sumidero (Sink) y estás funcionando. Recurre a los eventos cuando:- Necesitas comportamiento que abarca múltiples componentes sin flujo directo
- Necesitas que el modelo reaccione a reglas operativas (calendarios de turnos, cambios de prioridad, picos de demanda)
- Estás modelando sistemas lean o de demanda donde downstream pide a upstream
- Necesitas rastrear y reaccionar a métricas transversales (WIP móvil, utilización)

