← Volver al índice | Pivote Quarkus+Dapr
Análisis de Viabilidad: Migración Pekko → Quarkus + Dapr¶
Tipo: Investigación — Evaluación de Viabilidad
Audiencia: Equipo de desarrollo, arquitectos
Fecha: 20 de marzo de 2026
Relacionado con: Pivote Arquitectónico | Análisis Tecnológico
1. Inventario de Actores Pekko Actuales → Equivalentes Dapr¶
1.1 Mapeo Actor por Actor¶
| Actor Pekko (original) | Responsabilidad | Equivalente Dapr/Quarkus | Complejidad migración |
|---|---|---|---|
ImageProcessingActor |
Pre-procesado de imágenes (resize, limpieza, OpenCV) | Quarkus service + Virtual Thread — tarea CPU-bound sin estado | 🟢 Baja |
AIInferenceActor |
Invocación de LLM para identificación | LangChain4j @RegisterAiService — la interfaz CDI sustituye completamente al actor |
🟢 Baja |
SampleIngestionActor |
Ingesta de muestras desde múltiples fuentes | Dapr Bindings + Pub/Sub — webhooks M365, GSheets polling | 🟢 Baja |
RealTimeDetectionActor |
Streaming de video/frames desde cámara | Quarkus WebSocket + Virtual Threads — Java 25 maneja millones de conexiones | 🟡 Media |
Actor: Sesión Cámara |
Estado de conexión por dispositivo (gemelo digital) | Dapr State Management — estado por clave (session_id) en Redis | 🟢 Baja |
Actor: Pipeline IA |
Orquestación multi-paso (preproceso → inferencia → resultado) | Dapr Workflow — orquestación declarativa con retry, compensación | 🟢 Baja |
Actor: Ingesta Datos |
ETL de SharePoint/GSheets | Dapr Bindings (input bindings para Graph API webhooks) | 🟢 Baja |
Pekko Streams |
Backpressure y streaming reactivo | Quarkus Mutiny + SmallRye Reactive Messaging | 🟡 Media |
Cluster Sharding |
Distribución elástica de actores | Kubernetes auto-scaling + Dapr placement service | 🟢 Baja |
Supervision Tree |
Tolerancia a fallos jerárquica | K8s liveness/readiness probes + Dapr retry policies | 🟡 Media |
[!TIP] Resultado: 7 de 10 componentes son de migración baja. Los 3 de complejidad media tienen alternativas probadas en el ecosistema Quarkus+K8s.
1.2 Lo que Pekko Hace Bien y No se Necesita¶
| Capacidad Pekko | ¿Se necesita en IEO? | Alternativa |
|---|---|---|
| Cluster Sharding | No (no hay millones de usuarios concurrentes) | K8s HPA |
| Artery TCP Remoting | No (no hay cluster multi-nodo en MVP) | Dapr Service Invocation |
| Supervision Trees | Sí, pero simplificada | K8s probes + Dapr retry |
| Pekko Persistence | Sí (event sourcing) | Dapr State + PostgreSQL |
| Pekko Streams | Parcialmente (backpressure) | SmallRye Reactive Messaging + Kafka |
2. Máquinas de Estados Finitos (FSMs) del Sistema¶
2.1 FSM: Ciclo de Vida de una Muestra¶
stateDiagram-v2
[*] --> Capturada: Foto desde cámara/upload
Capturada --> Preprocesando: OpenCV limpieza
Preprocesando --> EnColaIA: Imagen normalizada
EnColaIA --> IdentificandoIA: Modelo disponible
IdentificandoIA --> IdentificadaIA: Confianza >= umbral
IdentificandoIA --> RequiereRevision: Confianza < umbral
IdentificadaIA --> PendienteConfirmacion: Espera validación humana
RequiereRevision --> PendienteConfirmacion: Prioridad alta
PendienteConfirmacion --> Confirmada: Investigador valida
PendienteConfirmacion --> Corregida: Investigador corrige especie/edad
Confirmada --> EnBaseDatos: Persistida con metadatos
Corregida --> EnBaseDatos: Persistida + feedback IA
EnBaseDatos --> EmbeddingsGenerados: Vectores en ChromaDB
EmbeddingsGenerados --> [*]: Disponible para búsqueda
Implementación Dapr:
| Estado | Building Block | Actor Pekko equivalente |
|---|---|---|
| Capturada → Preprocesando | Virtual Thread (CPU-bound) | ImageProcessingActor |
| EnColaIA → IdentificandoIA | Dapr Pub/Sub (evento imagen.lista) |
AIInferenceActor (cola interna) |
| IdentificandoIA | LangChain4j (@RegisterAiService) |
AIInferenceActor |
| PendienteConfirmacion | Dapr State (estado mutable por muestra) | Actor con FSM interna |
| Confirmada → EnBaseDatos | Dapr Pub/Sub (evento muestra.confirmada) |
SampleIngestionActor |
| → EmbeddingsGenerados | Dapr Workflow (paso de pipeline) | Pekko Streams |
2.2 FSM: Pipeline ETL de Carga Incremental¶
stateDiagram-v2
[*] --> Monitorizado: Fuente registrada
Monitorizado --> CambioDetectado: Polling/Webhook/CDC
CambioDetectado --> DescargandoDelta: Fetch datos nuevos
DescargandoDelta --> ValidandoEsquema: Datos descargados
ValidandoEsquema --> EsquemaOK: Sin cambios de estructura
ValidandoEsquema --> EsquemaCambiado: Columnas nuevas/eliminadas
EsquemaCambiado --> EsperandoAprobacion: Alerta a Responsable
EsperandoAprobacion --> EsquemaOK: Responsable aprueba
EsperandoAprobacion --> Rechazado: Responsable rechaza
Rechazado --> Monitorizado: Vuelve a monitorizar
EsquemaOK --> Normalizando: Aplicar transformaciones
Normalizando --> GenerandoEmbeddings: Datos normalizados
GenerandoEmbeddings --> Persistiendo: Vectores listos
Persistiendo --> CargaCompletada: PostgreSQL + ChromaDB + MinIO
CargaCompletada --> LogRegistrado: Auditoría inmutable
LogRegistrado --> Monitorizado: Siguiente ciclo
CambioDetectado --> ErrorConexion: Fuente no disponible
ErrorConexion --> Monitorizado: Retry con backoff
Implementación Dapr:
| Transición | Building Block | Detalle |
|---|---|---|
| Monitorizado → CambioDetectado | Dapr Input Binding (GSheets, Graph API, MQTT) | Configuración declarativa YAML |
| Descargando → Validando | Dapr Workflow Activity | Paso con timeout y retry |
| EsquemaCambiado → EsperandoAprobacion | Dapr State + Pub/Sub (notificación) | Estado persistido, evento esquema.cambio |
| Normalizando → Embeddings → Persistiendo | Dapr Workflow (3 activities secuenciales) | Con compensación si falla |
| Log | Dapr State (append-only) | Log inmutable por dataset |
2.3 FSM: Entrenamiento LoRA (Long-Running Process)¶
stateDiagram-v2
[*] --> Planificado: Configuración recibida
Planificado --> PreparandoDataset: Descarga y preproceso imágenes
PreparandoDataset --> DatasetListo: Captions + tags generados
DatasetListo --> Entrenando: GPU disponible
DatasetListo --> EsperandoGPU: GPU ocupada
EsperandoGPU --> Entrenando: GPU liberada
Entrenando --> Entrenando: Progreso (epoch N/M)
Entrenando --> EntrenamientoCompletado: Todas las epochs OK
Entrenando --> ErrorEntrenamiento: OOM / error GPU
ErrorEntrenamiento --> Planificado: Retry con params ajustados
EntrenamientoCompletado --> Validando: Test de precisión
Validando --> Aprobado: Precisión >= 80%
Validando --> Rechazado2: Precisión < 80%
Rechazado2 --> Planificado: Re-entrenar con más datos
Aprobado --> Desplegando: Copiar a Ollama
Desplegando --> Activo: Modelo disponible
Activo --> [*]
Implementación Dapr:
| Estado | Building Block | Ventaja vs Pekko |
|---|---|---|
| Todo el workflow | Dapr Workflow | Estado persiste entre reinicios (Pekko pierde estado en crash) |
| Progreso | Dapr State (training:{id} → {epoch, loss, eta}) |
Consultable via API REST |
| EsperandoGPU | Dapr Timer + externalización | Sin actor bloqueado en memoria |
| Notificaciones | Dapr Pub/Sub | Desacoplado del proceso |
2.4 FSM: Sesión de Cámara en Tiempo Real¶
stateDiagram-v2
[*] --> Desconectado
Desconectado --> Conectando: WebSocket abierto
Conectando --> Activa: Handshake OK + auth
Conectando --> ErrorAuth: Token inválido
ErrorAuth --> Desconectado
Activa --> Streaming: Frames recibidos
Streaming --> Streaming: Frame N procesado
Streaming --> Pausada: Sin frames (>30s)
Pausada --> Streaming: Frames reanudados
Pausada --> Desconectada: Timeout (5min)
Streaming --> BufferOffline: Pérdida de conexión
BufferOffline --> Sincronizando: Conexión recuperada
Sincronizando --> Activa: Buffer vaciado
Activa --> Desconectado: Cierre explícito
Desconectada --> Desconectado
Implementación Dapr:
| Aspecto | Pekko (original) | Quarkus + Dapr |
|---|---|---|
| WebSocket | Pekko HTTP | Quarkus WebSocket Next (Jakarta WebSocket) |
| Estado de sesión | Actor en memoria | Dapr State en Redis (persiste entre reinicios) |
| Concurrencia | 1 actor por sesión | 1 Virtual Thread por sesión (Java 25 — millones posibles) |
| Buffer offline | Actor interno | Dapr State + cola Kafka |
| Timeout | Pekko Scheduler | Quarkus @Scheduled o Dapr Timer |
3. Pekko vs Dapr — Comparativa Definitiva¶
3.1 Filosofía¶
| Aspecto | Apache Pekko | Dapr |
|---|---|---|
| Modelo | Actor Model (Erlang/OTP) | Sidecar + Building Blocks |
| Código | Escribes lógica de actores, supervisión, mensajes | Escribes lógica de negocio, Dapr maneja la infraestructura |
| Estado | Encapsulado en RAM del actor | Externalizado (Redis, PostgreSQL) |
| Resiliencia | Supervision trees (código custom) | Retry policies + K8s probes (declarativo YAML) |
| Distribución | Cluster Sharding + Artery (complejo) | K8s scaling + Dapr placement (automático) |
| Latencia | Ultra-baja (~μs entre actores) | Baja (~1-5ms via sidecar HTTP/gRPC) |
| Curva | Alta (conceptos: actores, mailbox, supervision, stash, become) | Baja (HTTP/gRPC estándar + YAML) |
3.2 Cuándo Pekko es Mejor¶
| Escenario | ¿Aplica al IEO? |
|---|---|
| Trading de alta frecuencia (μs de latencia) | ❌ No |
| Telecomunicaciones con millones de sesiones simultáneas | ❌ No |
| Sistemas distribuidos multi-datacenter con consistencia eventual compleja | ❌ No |
| Procesamiento de streams masivos con backpressure a nivel de byte | ❌ No (Kafka cubre esto) |
3.3 Cuándo Dapr es Mejor¶
| Escenario | ¿Aplica al IEO? |
|---|---|
| Sistema de integración multi-fuente (GSheets, SharePoint, Oracle, IoT) | ✅ Sí — core del proyecto |
| Orquestación de workflows (ETL, entrenamiento IA) | ✅ Sí |
| Microservicios en Kubernetes con escalado automático | ✅ Sí — DragonCloud |
| Estado de procesos largos consultable via API | ✅ Sí — LoRA training, batch embeddings |
| Pub/Sub entre servicios desacoplados | ✅ Sí — eventos muestra.creada, esquema.cambio |
| Developers centrados en lógica de negocio, no en infraestructura | ✅ Sí — equipo pequeño |
[!IMPORTANT] Veredicto: Pekko es un martillo de precisión para cirugía de latencia (telecoms, trading). El IEO necesita un sistema de integración con workflows y observabilidad — Dapr está diseñado exactamente para esto. Con Dapr, el código Quarkus se centra en la lógica de negocio: identificar especies, procesar datos, generar embeddings. La coordinación de actores desaparece del código.
4. Evaluación de Viabilidad: Escenarios Críticos¶
4.1 Matriz de Viabilidad¶
| Escenario | Viabilidad Quarkus+Dapr | Riesgo | Mitigación |
|---|---|---|---|
| Identificación de especie via cámara | ✅ Alta | Latencia WebSocket | Virtual Threads eliminan bloqueo |
| ETL incremental multi-fuente | ✅ Alta | Formatos heterogéneos | Dapr Bindings + validación custom |
| Entrenamiento LoRA (horas/días) | ✅ Alta | Estado perdido en crash | Dapr Workflow persiste estado automáticamente |
| Búsqueda semántica CAG+RAG | ✅ Alta | Latencia RAG | LangChain4j con caché KV-Cache + Redis |
| Video streaming 60fps | ✅ Media-Alta | Overhead sidecar (~1-5ms) | WebSocket directo (sin pasar por Dapr) para frames |
| Sincronización offline barco | ✅ Alta | Sin red durante días | Dapr State local + sync via cola al volver |
| Dashboard en tiempo real | ✅ Alta | SSE/WebSocket concurrente | Virtual Threads — sin límite práctico |
| Migración a K8s | ✅ Alta | Complejidad operativa | Dapr simplifica networking inter-servicio |
| Multi-modelo IA por departamento | ✅ Alta | Gestión de modelos | LangChain4j multi-model config centralizada |
| Auditoría ENS | ✅ Alta | Trazabilidad | Dapr + OpenTelemetry — tracing completo |
4.2 Escenario de Mayor Riesgo: Video Streaming¶
El único escenario donde Pekko tiene ventaja teórica es el streaming de video a 60fps, donde el overhead del sidecar Dapr (~1-5ms) podría ser un factor.
Solución arquitectónica:
flowchart LR
CAM["Cámara 60fps"] -->|"WebSocket directo"| QK["Quarkus WebSocket - Virtual Thread"]
QK -->|"frame limpio cada 1s"| DAPR["Dapr Service Invocation"]
DAPR --> OLLAMA["Ollama (inferencia)"]
OLLAMA -->|"resultado"| DAPR
DAPR -->|"SSE"| UI["Frontend"]
style QK fill:#2ecc71,color:#fff
style DAPR fill:#9b59b6,color:#fff
El truco: el WebSocket de video va directo a Quarkus (sin Dapr sidecar) porque es una conexión punto-a-punto de alta frecuencia. Dapr solo se involucra para la inferencia (1 request/segundo, no 60). Es el patrón "sidecar bypass for hot path".
5. Código que Desaparece con la Migración¶
5.1 Lo que hay que escribir con Pekko (y ya no)¶
// ❌ ANTES: ~200 líneas de actor + supervisión + protocolo
public class AIInferenceActor extends AbstractBehavior<AIInferenceActor.Command> {
sealed interface Command permits InferImage, GetStatus, Shutdown {}
record InferImage(String imagePath, ActorRef<Result> replyTo) implements Command {}
// ... 50 líneas de protocolo
@Override
public Receive<Command> createReceive() {
return newReceiveBuilder()
.onMessage(InferImage.class, this::onInferImage)
.onMessage(GetStatus.class, this::onGetStatus)
.onSignal(PreRestart.class, signal -> onPreRestart())
// ... 30 líneas de handling
.build();
}
// ... 100 líneas de lógica + retry + supervision
}
// ✅ DESPUÉS: ~15 líneas con Quarkus + LangChain4j
@RegisterAiService(modelName = "qwen25-vl")
@SystemMessage("Eres un experto en identificación de especies marinas del IEO...")
public interface IdentificadorEspecies {
Identificacion identificar(@V("prompt") String prompt, @ImageUrl String imagenUrl);
}
5.2 Reducción de Código Estimada¶
| Componente | Líneas con Pekko | Líneas con Quarkus+Dapr | Reducción |
|---|---|---|---|
| Actores IA (4 types) | ~800 | ~60 (interfaces CDI) | -92% |
| Protocolos de mensajes | ~400 | 0 (HTTP/gRPC estándar) | -100% |
| Supervisión y recovery | ~300 | ~20 (YAML retry policies) | -93% |
| Cluster y sharding | ~200 | 0 (K8s automático) | -100% |
| Workflows ETL | ~500 | ~150 (Dapr Workflow) | -70% |
| Total | ~2.200 | ~230 | -90% |
6. Conclusión¶
[!IMPORTANT] La migración de Pekko a Quarkus + Dapr es VIABLE y RECOMENDADA para el proyecto IEO.
| Factor | Evaluación |
|---|---|
| Viabilidad técnica | ✅ Alta — todos los escenarios cubiertos |
| Riesgo mayor | 🟡 Video streaming (mitigado con sidecar bypass) |
| Reducción de código | ~90% menos código de infraestructura |
| Foco en negocio | El equipo escribe lógica de identificación, no actores |
| Cloud-native | Docker → K8s (DragonCloud) nativo |
| IA | LangChain4j ≥ Spring AI en patrones agénticos |
| Java 25 | Virtual Threads eliminan la necesidad primaria de actores |
Decisión: Proceder con la migración completa de la documentación al nuevo stack.
Documentos Relacionados¶
| Nivel | Documento | Descripción |
|---|---|---|
| Arquitectura | Pivote Quarkus+Dapr | Stack propuesto completo |
| Investigación | Análisis Tecnológico | Documento original con Pekko (a migrar) |
| Arquitectura | Arquitectura del Sistema | Stack actual (a migrar) |