SagaDefinition
A interface base que toda saga deve implementar.
Definição
public interface SagaDefinition<C> {
/**
* Define os steps da saga usando o builder.
*
* @param builder O builder fluent para configurar os steps
*/
void define(SagaBuilder<C> builder);
}
Parâmetros de Tipo
| Parâmetro | Descrição |
|---|---|
C | Tipo do contexto da saga (deve ser serializável para JSONB) |
Exemplo de Implementação
@Saga("pix-payment")
public class PixPaymentSaga implements SagaDefinition<PixContext> {
private final DictService dictService;
private final BalanceService balanceService;
private final BacenService bacenService;
public PixPaymentSaga(
DictService dictService,
BalanceService balanceService,
BacenService bacenService
) {
this.dictService = dictService;
this.balanceService = balanceService;
this.bacenService = bacenService;
}
@Override
public void define(SagaBuilder<PixContext> builder) {
builder
.step("validate-dict")
.invoke(this::validateDict)
.compensate(this::invalidateDict)
.step("block-balance")
.invoke(this::blockBalance)
.compensate(this::unblockBalance)
.step("transmit-to-bacen")
.invoke(this::transmitToBacen)
.retry(exponential(3, Duration.ofSeconds(1)))
.build();
}
// --- Invoke Methods ---
private PixContext validateDict(PixContext ctx) {
String token = dictService.validate(ctx.dictKey());
return ctx.withValidationToken(token);
}
private PixContext blockBalance(PixContext ctx) {
String blockId = balanceService.block(ctx.payerId(), ctx.amount());
return ctx.withBlockId(blockId);
}
private PixContext transmitToBacen(PixContext ctx) {
bacenService.transmit(ctx.transactionId(), ctx.amount());
return ctx;
}
// --- Compensate Methods ---
private void invalidateDict(PixContext ctx) {
dictService.invalidate(ctx.validationToken());
}
private void unblockBalance(PixContext ctx) {
balanceService.unblock(ctx.blockId());
}
}
️ Anotação @Saga
A anotação @Saga registra a definição no container Spring:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Component
public @interface Saga {
/**
* Nome único da saga usado para identificação e disparo.
*/
String value();
/**
* Descrição opcional para documentação.
*/
String description() default "";
}
Atributos
| Atributo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
value | String | Nome único da saga | |
description | String | Descrição opcional para documentação |
Exemplo
@Saga(
value = "pix-payment",
description = "Processa pagamentos PIX com compensação automática"
)
public class PixPaymentSaga implements SagaDefinition<PixContext> {
// ...
}
Regras Importantes
Não use @Transactional
@Saga("pix-payment")
@Transactional // <DocIcon name="alert" /> ERRADO! O engine gerencia as transações
public class PixPaymentSaga implements SagaDefinition<PixContext> {
// ...
}
O Sagaweaw gerencia todas as transações internamente. Usar @Transactional pode causar comportamento inesperado.
Injeção de Dependências
O Sagaweaw é compatível com injeção de dependências do Spring:
@Saga("order-processing")
public class OrderProcessingSaga implements SagaDefinition<OrderContext> {
private final StockService stockService;
private final PaymentService paymentService;
// Injeção via construtor (recomendado)
public OrderProcessingSaga(
StockService stockService,
PaymentService paymentService
) {
this.stockService = stockService;
this.paymentService = paymentService;
}
@Override
public void define(SagaBuilder<OrderContext> builder) {
// ...
}
}