Pular para o conteúdo principal

Ciclo de Vida

Cada saga passa por estados bem definidos durante sua execução. Isso garante rastreabilidade completa e recuperação previsível.


Estados da Saga

┌─────────┐
│ STARTED │
└────┬────┘


┌───────────┐
│ EXECUTING │◄──────────────────┐
└─────┬─────┘ │
│ │
┌─────────────┴─────────────┐ (retry)
│ │ │
(sucesso) (falha) │
│ │ │
▼ ▼ │
┌───────────┐ ┌─────────────┐ │
│ COMPLETED │ │ COMPENSATING│─────┘
└───────────┘ └──────┬──────┘

┌──────────────┴──────────────┐
│ │
(sucesso) (falha)
│ │
▼ ▼
┌─────────────┐ ┌────────┐
│ COMPENSATED │ │ FAILED │
└─────────────┘ └────────┘

Descrição dos Estados

STARTED

Estado inicial quando a saga é criada.

SagaExecution execution = sagaManager.start(PixPaymentSaga.class, context);
// execution.sagaId() retorna o UUID gerado para acompanhamento
AspectoValor
DuraçãoMilissegundos
PróximoEXECUTING
TriggersagaManager.start()

EXECUTING

A saga está processando os steps sequencialmente.

EXECUTING: step 1 de 4 - validate-dict ●
AspectoValor
DuraçãoVariável
PróximoCOMPLETED ou COMPENSATING
TriggerInício do primeiro step

COMPLETED

Todos os steps foram executados com sucesso. Estado final positivo.

COMPLETED ✓ - 4/4 steps executados em 2.3s
AspectoValor
DuraçãoFinal
Próximo-
TriggerÚltimo step concluído

COMPENSATING

Um step falhou e as compensações estão sendo executadas em ordem inversa.

COMPENSATING: rollback step 2 de 3 - block-balance ↩️
AspectoValor
DuraçãoVariável
PróximoCOMPENSATED ou FAILED
TriggerFalha em step após retries

COMPENSATED

Todas as compensações foram executadas com sucesso. A saga foi revertida.

COMPENSATED ↩️ - 3 compensações executadas em 0.8s
AspectoValor
DuraçãoFinal
Próximo-
TriggerÚltima compensação concluída

FAILED

Estado terminal de falha. Ocorre quando:

  • Um PIVOT falha após todas as tentativas de retry
  • Uma compensação falha (saga vai para Dead Letter)
FAILED ✗ - transmit-to-bacen: timeout após 3 tentativas
AspectoValor
DuraçãoFinal
PróximoManual (Dead Letter)
TriggerFalha irrecuperável

Transições de Estado

Cenário: Sucesso Completo

STARTED → EXECUTING → COMPLETED
│ │ │
│ │ └─ Fim
│ └─ Steps 1, 2, 3, 4 ✓
└─ Início

Cenário: Falha com Compensação

STARTED → EXECUTING → COMPENSATING → COMPENSATED
│ │ │ │
│ │ │ └─ Fim (rollback OK)
│ │ └─ comp 2, comp 1 ↩️
│ └─ step 1 ✓, step 2 ✓, step 3 ✗
└─ Início

Cenário: Falha em PIVOT

STARTED → EXECUTING → COMPENSATING → FAILED
│ │ │ │
│ │ │ └─ Dead Letter
│ │ └─ comp 2 ✓, comp 1 ✗
│ └─ step 1 ✓, step 2 ✓, step 3 (PIVOT) ✗
└─ Início

Consulta de Estado

Por ID (Java)

// Via Observability API: GET /api/sagas/{sagaId}
// Via SagaEngine (injeção direta):
Optional<SagaInstance> instance = engine.findById(sagaId);
instance.ifPresent(i -> {
System.out.println("Status: " + i.status());
System.out.println("Steps: " + i.steps().size());
});

Via REST API

# Sagas com falha
GET /api/sagas?status=FAILED

# Saga específica
GET /api/sagas/{id}

# Métricas agregadas
GET /api/sagas/metrics
dica

A Observability API fornece filtros por status, nome, data e chave de idempotência. Veja Observability API →.


Eventos de Ciclo de Vida

O Sagaweaw emite eventos para cada transição:

@Component
public class SagaEventListener {

@EventListener
public void onSagaStarted(SagaStartedEvent event) {
log.info("Saga {} started", event.getSagaId());
}

@EventListener
public void onSagaCompleted(SagaCompletedEvent event) {
log.info("Saga {} completed in {}ms",
event.getSagaId(),
event.getDuration());
}

@EventListener
public void onSagaFailed(SagaFailedEvent event) {
log.error("Saga {} failed: {}",
event.getSagaId(),
event.getError());
}
}

Próximos Passos