SagaBuilder
A DSL fluente para definir os steps da saga.
API
public interface SagaBuilder<C> {
/**
* Inicia a definição de um novo step.
*/
StepBuilder<C> step(String name);
/**
* Finaliza a definição da saga.
*/
void build();
}
StepBuilder
Cada step é configurado através do StepBuilder:
public interface StepBuilder<C> {
/**
* Define a função de execução do step.
*/
StepBuilder<C> invoke(Function<C, C> action);
/**
* Define a função de compensação (rollback).
*/
StepBuilder<C> compensate(Consumer<C> compensation);
/**
* Configura a política de retry.
*/
StepBuilder<C> retry(RetryPolicy policy);
/**
* Adiciona um timeout ao step.
*/
StepBuilder<C> timeout(Duration timeout);
/**
* Define condição para execução do step.
*/
StepBuilder<C> when(Predicate<C> condition);
/**
* Inicia o próximo step (encadeia).
*/
StepBuilder<C> step(String name);
/**
* Finaliza a definição.
*/
void build();
}
Exemplos
Step Básico
builder
.step("validate")
.invoke(this::validate)
.build();
Step com Compensação
builder
.step("block-balance")
.invoke(this::blockBalance)
.compensate(this::unblockBalance)
.build();
Step com Retry
builder
.step("call-external-api")
.invoke(this::callApi)
.compensate(this::rollbackApi)
.retry(exponential(3, Duration.ofSeconds(1)))
.build();
Step com Timeout
builder
.step("slow-operation")
.invoke(this::slowOperation)
.timeout(Duration.ofSeconds(30))
.build();
Step Condicional
builder
.step("send-premium-notification")
.invoke(this::sendPremiumNotification)
.when(ctx -> ctx.isPremiumUser())
.build();
Encadeamento Completo
@Override
public void define(SagaBuilder<OrderContext> builder) {
builder
// Step 1: COMPENSABLE
.step("reserve-stock")
.invoke(this::reserveStock)
.compensate(this::releaseStock)
.timeout(Duration.ofSeconds(5))
// Step 2: COMPENSABLE
.step("process-payment")
.invoke(this::processPayment)
.compensate(this::refundPayment)
.retry(exponential(3, Duration.ofSeconds(2)))
// Step 3: PIVOT (sem compensação)
.step("confirm-order")
.invoke(this::confirmOrder)
.retry(exponential(5, Duration.ofSeconds(1)))
// Step 4: CONDICIONAL
.step("send-vip-gift")
.invoke(this::sendVipGift)
.when(ctx -> ctx.isVipCustomer())
// Step 5: RETRIABLE
.step("send-confirmation")
.invoke(this::sendConfirmation)
.retry(infinite())
.build();
}
Métodos de Invoke
Assinatura
Function<C, C> action
O método recebe o contexto atual e deve retornar um novo contexto (imutabilidade).
Exemplo
private OrderContext reserveStock(OrderContext ctx) {
// Executa a operação
String reservationId = stockService.reserve(ctx.items());
// Retorna novo contexto com o resultado
return ctx.withReservationId(reservationId);
}
Métodos de Compensate
Assinatura
Consumer<C> compensation
O método recebe o contexto e não retorna nada (void).
Exemplo
private void releaseStock(OrderContext ctx) {
// Usa dados salvos no contexto para reverter
stockService.release(ctx.reservationId());
}