Pular para o conteúdo principal

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());
}

Relacionados