SagaContext
O objeto imutável que viaja entre os steps da saga.
Conceito
O SagaContext é um padrão, não uma interface. Você define seu próprio context como um record ou classe imutável.
Implementação com Record
public record OrderContext(
// Dados de entrada (definidos na criação)
String orderId,
String customerId,
List<OrderItem> items,
BigDecimal totalAmount,
// Outputs dos steps (populados durante execução)
String stockReservationId,
String paymentIntentId,
String shippingTrackingId
) {
/**
* Cria um contexto inicial com apenas os dados de entrada.
*/
public static OrderContext create(Order order) {
return new OrderContext(
order.getId(),
order.getCustomerId(),
List.copyOf(order.getItems()),
order.getTotal(),
null, null, null // Outputs iniciam nulos
);
}
// --- Builders imutáveis ---
public OrderContext withStockReservationId(String id) {
return new OrderContext(
orderId, customerId, items, totalAmount,
id, paymentIntentId, shippingTrackingId
);
}
public OrderContext withPaymentIntentId(String id) {
return new OrderContext(
orderId, customerId, items, totalAmount,
stockReservationId, id, shippingTrackingId
);
}
public OrderContext withShippingTrackingId(String id) {
return new OrderContext(
orderId, customerId, items, totalAmount,
stockReservationId, paymentIntentId, id
);
}
}
Implementação com Lombok
@Value
@With
@Builder
public class OrderContext {
String orderId;
String customerId;
List<OrderItem> items;
BigDecimal totalAmount;
String stockReservationId;
String paymentIntentId;
String shippingTrackingId;
public static OrderContext create(Order order) {
return OrderContext.builder()
.orderId(order.getId())
.customerId(order.getCustomerId())
.items(List.copyOf(order.getItems()))
.totalAmount(order.getTotal())
.build();
}
}
// Uso
ctx.withStockReservationId("RES-123");
Requisitos
Deve ser
- Serializável para JSON — O Sagaweaw persiste como JSONB
- Imutável — Cada step retorna uma nova instância
- Sem referências circulares — JSON não suporta
Evite
- Coleções mutáveis (ArrayList, HashMap)
- Referências a entidades JPA
- Objetos complexos não serializáveis
Serialização
O context é serializado automaticamente:
{
"orderId": "ORD-9912",
"customerId": "CUST-001",
"items": [
{"productId": "PROD-1", "quantity": 2}
],
"totalAmount": 299.90,
"stockReservationId": "RES-123",
"paymentIntentId": "pi_abc123",
"shippingTrackingId": null
}
Uso nos Steps
Invoke
private OrderContext reserveStock(OrderContext ctx) {
// Usa dados do contexto
String reservationId = stockService.reserve(ctx.items());
// Retorna NOVO contexto com o resultado
return ctx.withStockReservationId(reservationId);
}
Compensate
private void releaseStock(OrderContext ctx) {
// Usa o ID salvo anteriormente
stockService.release(ctx.stockReservationId());
}