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 | Sí |
¿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:
- Define una secuencia de actividades (funciones)
- Persiste el estado entre actividades (event sourcing)
- Se recupera automáticamente de caídas (durabilidad)
- 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 |