Saltar a contenido

← Volver al índice

Spike: Dapr Workflows en Java

Tipo: Documentación Técnica — Investigación
Estado: 📋 Pendiente (planificado para Sprint 0)
Relacionado con: Implementation Plan — S2 Motor Ejecución


1. ¿Qué es un Spike?

Un spike es un concepto de metodología ágil (Scrum/XP) que significa:

Una investigación técnica acotada en tiempo (timebox) cuyo objetivo es reducir incertidumbre antes de comprometer puntos de historia.

Características

Aspecto Spike Story normal
Output Una decisión documentada Código de producción
Estimación En horas/días (no SP) En Story Points
Duración Fija (1-2 días máx) Variable
Demo "Aprendimos X, decisión es Y" "Funcionalidad Z funciona"
Se cuenta en velocidad No

¿Cuándo hacer un spike?

  • Cuando un item del backlog tiene incertidumbre técnica alta
  • Cuando no puedes estimar con confianza (pones ? en planning poker)
  • Cuando la tecnología es nueva para el equipo
  • Cuando el riesgo de bloqueo en el sprint es inaceptable

2. ¿Por qué un spike para Dapr Workflows?

Dapr Workflows es el motor que interpretará las definiciones de flows y las ejecutará como secuencias de actividades. Es el componente central del Sprint 2 (38 SP).

Riesgos sin spike

Riesgo Impacto
API de Workflows en Java no se comporta como esperamos Bloquea 38 SP
El event sourcing de Dapr no persiste como asumimos Rediseño del modelo de ejecución
La integración Quarkus ↔ Dapr sidecar tiene gotchas Debugging costoso en sprint
Los timers/delays de Dapr funcionan diferente a lo documentado Reescritura de nodos Wait

Riesgos con spike (mitigados)

  • ✅ Sabemos exactamente cómo funciona la API
  • ✅ Tenemos un ejemplo funcionando
  • ✅ Podemos estimar S2 con confianza
  • ✅ Hemos identificado gotchas antes de comprometer SP

3. Plan del spike — Timebox: 2 días

Día 1: Workflow trivial end-to-end

Objetivo: Ejecutar un workflow Dapr de 3 actividades en Quarkus.

// Workflow trivial: Log → Wait → Log
@DaprWorkflow
public class TrivialWorkflow extends Workflow {

    @Override
    public WorkflowStub create() {
        return ctx -> {
            // Activity 1: Log inicio
            ctx.callActivity("LogActivity",
                "Flow started at " + Instant.now()).await();

            // Activity 2: Wait 5 seconds
            ctx.createTimer(Duration.ofSeconds(5)).await();

            // Activity 3: Log fin
            ctx.callActivity("LogActivity",
                "Flow completed at " + Instant.now()).await();
        };
    }
}
# Ejecutar con Dapr sidecar
dapr run --app-id pet-flows \
         --app-port 8080 \
         --dapr-http-port 3500 \
         -- ./mvnw quarkus:dev

Día 2: Validar patrones del motor de ejecución

Test Qué validamos
Fan-out ¿Se puede ejecutar actividades en paralelo?
Condicional ¿Se puede evaluar una condición y bifurcar?
Event sourcing ¿Dapr persiste el estado entre actividades?
Recuperación Si el proceso se cae, ¿se reanuda?
Timer ¿Los delays funcionan como esperamos?
Sub-workflow ¿Se puede llamar un workflow desde otro?

4. Output esperado

Documento de decisión

## Spike Result: Dapr Workflows

**Fecha**: [fecha]
**Resultado**: GO / NO-GO / GO con ajustes

### Lo que funciona
- [lista de features validadas]

### Gotchas encontradas
- [lista de problemas/sorpresas]

### Decisiones tomadas
- Patrón X para condicionales
- Patrón Y para fan-out
- Timer resolution = Z

### Impacto en estimación S2
- Story 2.1 mantiene 13 SP / cambia a N SP
- [ajustes si los hay]

Código prototipo

El código del spike no entra en producción pero se conserva en dkv-pet-flows-api/src/test/java/spike/ como referencia.


5. Contexto técnico — Dapr Workflows

¿Qué es un Dapr Workflow?

Un Workflow de Dapr es un orquestador durable que:

  1. Define una secuencia de actividades (funciones)
  2. Persiste el estado entre actividades (event sourcing)
  3. Se recupera automáticamente de caídas (durabilidad)
  4. Soporta timers, sub-workflows, y fan-out/fan-in

Componentes

┌─────────────────────────────────────────────┐
│  Quarkus App (dkv-pet-flows-api)            │
│                                             │
│  WorkflowRuntime                            │
│    ├── FlowExecutionWorkflow                │
│    │     ├── TriggerActivity                │
│    │     ├── ConditionActivity              │
│    │     ├── WaitActivity (timer)           │
│    │     ├── PushNotificationActivity       │
│    │     └── EmailActivity                  │
│    └── WorkflowClient (SDK)                 │
│                                             │
└────────────────┬────────────────────────────┘
                 │ gRPC / HTTP
┌────────────────▼────────────────────────────┐
│  Dapr Sidecar (daprd)                       │
│    ├── Workflow Engine                      │
│    ├── State Store (PostgreSQL)             │
│    └── Event Sourcing (automatic)           │
└─────────────────────────────────────────────┘

Ejemplo de mapping: Flow definition → Workflow

Flow JSON:
  Trigger("Consulta Finalizada")
    → Wait(5 días)
      → Condition("pushEnabled == true")
        → YES: PushNotification("Encuesta")
        → NO:  Email("Encuesta fallback")
      → RegisterEvent("Event Store")

Dapr Workflow:
  Activity: checkTrigger(consultaFinalizada)
  Timer: createTimer(5 days)
  Activity: evaluateCondition(pushEnabled)
  Branch YES: Activity: sendPush(encuesta)
  Branch NO:  Activity: sendEmail(encuesta)
  Activity: registerEvent(eventStore)

Documentos Relacionados

Nivel Documento
Plan Implementation Plan — S0/S2
Arquitectura Arquitectura del Sistema
Nodos Catálogo 40 Nodos