← Volver al índice | Siguiente: Dapr vs Pekko
Motor de Flujos Dinámicos (Patrón Intérprete)¶
Tipo: Documentación Técnica — Core Architecture
Audiencia: Ingeniería (Backend & Frontend)
Fecha: 04 de Abril de 2026
1. El Desafío del "Drag and Drop"¶
En el frontend (Jaraxa Flow Builder), los usuarios de negocio diseñan flujos visuales colocando nodos en un lienzo (ej. "Enviar Correo" → "Esperar 2 días" → "Verificar SMS").
El desafío arquitectónico es: ¿Cómo ejecutamos estos flujos diseñados por el usuario si nuestro orquestador (Dapr Workflow) requiere compilar el flujo en clases de Java estáticas?
La respuesta es el Patrón Intérprete.
2. El Orquestador: DynamicFlowInterpreterWorkflow.java¶
En lugar de crear una clase por cada flujo visual, nuestro backend compila una única clase de orquestación.
Este Workflow no contiene lógica de negocio específica. Actúa como un motor de ajedrez que "lee" las jugadas introducidas en un archivo de configuración (JSON). Cuando el sistema DKV lanza un evento (ej. abandono de mascota), se inicializa una nueva instancia aislada de esta clase pasándole el JSON del flujo dibujado.
Diagrama de Ejecución¶
El siguiente diagrama detalla cómo un proceso de negocio de varios días se orquesta utilizando el Patrón Intérprete, y cómo Dapr interviene suspendiendo y restaurando la memoria de la aplicación.
sequenceDiagram
participant DB as 🗄️ Database (JSON)
participant RMQ as 🐰 RabbitMQ
participant BW as ⚙️ BaseWorkflow (Java)
participant Dapr as 🛡️ Dapr Sidecar
participant Act as 🛠️ Activities (Worker)
Note over DB,Act: Fase 1: Inicialización
RMQ->>BW: Evento: "Paciente Abandonó" + Flow ID
BW->>DB: Extraer JSON del Flow dibujado
DB-->>BW: Grafo de nodos (JSON)
BW->>BW: Parsear nodo inicial
Note over DB,Act: Fase 2: Ejecución Activa
BW->>Act: ctx.callActivity("EnviarEmail", configNodo)
Act-->>BW: Resultado Email
BW->>Dapr: Guardar resultado en historial
BW->>BW: Leer siguiente nodo en el JSON
Note over DB,Act: Fase 3: Suspensión y Drenaje de Recusos
BW->>Dapr: ctx.createTimer("Wait 2 days")
Note over BW: El hilo de Java SE APAGA (0% CPU)<br/>Toda memoria local decae.
Dapr->>Dapr: Persiste estado (Redis/Postgres) automáticamente
Note over DB,Act: Fase 4: Reanudación (Event Sourcing)
Dapr-->>BW: Despierta Workflow (Timer Expirado)
BW->>BW: RE-EJECUTA CÓDIGO (Replay)<br/>Pero salta el "EnviarEmail" gracias al historial
BW->>Act: ctx.callActivity("CheckDB")
3. Dinamismo mediante "Workflow as Code"¶
Pese a que el código Java del Base Workflow no se modifica, el comportamiento es infinito y altamente dinámico.
Todo el proceso se define de forma imperativa con Dapr:
// Pseudocódigo simplificado del Motor Intérprete
public void run(WorkflowContext ctx, String userFlowJson) {
Graph graph = Parser.parse(userFlowJson);
Node current = graph.getStartNode();
while(current != null) {
if (current.is("HTTP")) {
// Ejecutar llamada al exterior de manera segura
result = ctx.callActivity(GenericHttp.class, current.props());
}
else if (current.is("SLEEP")) {
// Dapr hiberna el proceso hasta el tiempo indicado por el usuario
ctx.createTimer(Duration.ofDays(current.config("days"))).await();
}
// Navegar al siguiente nodo de forma dinámica según la respuesta
current = graph.next(current, result);
}
}
Ventaja Frente a Scripts u otros Motores¶
Si construyéramos nuestro propio motor leyendo JSON, tendríamos que manejar a mano las desconexiones, base de datos de timers, dead-letter proxies, serialización de varibles e índices. Dapr nos entrega la "hibernación distribuida" a nivel de infraestructura para que nosotros nos limitemos a iterar un archivo JSON sabiendo que la memoria no se volatizará entre pasos.
Documentos Relacionados¶
| Nivel | Documento | Descripción |
|---|---|---|
| Concepto | Decisión Dapr vs Pekko | Por qué se escogió "Workflow As Code" en lugar de Modelos de Actores |
| Negocio | MVP: Dinamización | Utilización de este motor para retener pacientes |