RetryPolicy
Políticas de retry configuráveis para cada step.
Tipos de Políticas
exponential()
Backoff exponencial com jitter. Recomendado para a maioria dos casos.
.retry(exponential(3, Duration.ofSeconds(1)))
// Tentativas: 1s, 2s, 4s (com jitter)
| Parâmetro | Tipo | Descrição |
|---|---|---|
maxAttempts | int | Número máximo de tentativas |
initialDelay | Duration | Delay inicial entre tentativas |
Com limites customizados
.retry(exponential()
.maxAttempts(5)
.initialDelay(Duration.ofSeconds(1))
.maxDelay(Duration.ofMinutes(5))
.multiplier(2.0)
.jitterFactor(0.1))
fixed()
Delay fixo entre tentativas.
.retry(fixed(3, Duration.ofSeconds(5)))
// Tentativas: 5s, 5s, 5s
| Parâmetro | Tipo | Descrição |
|---|---|---|
maxAttempts | int | Número máximo de tentativas |
delay | Duration | Delay fixo entre tentativas |
infinite()
Retry infinito. Use apenas para operações que devem eventualmente ter sucesso.
.retry(infinite())
// Tentativas: 1min, 2min, 4min, 8min... (até maxDelay)
Com limites
.retry(infinite()
.initialDelay(Duration.ofMinutes(1))
.maxDelay(Duration.ofHours(1)))
Atenção
Use infinite() apenas para operações idempotentes como notificações ou atualizações de cache.
none()
Sem retry. Falha na primeira tentativa resulta em compensação.
.retry(none())
// Falha imediatamente
Comparativo
| Política | Tentativas | Delay | Uso |
|---|---|---|---|
exponential() | Limitado | Crescente | APIs externas, bancos |
fixed() | Limitado | Constante | Operações simples |
infinite() | Ilimitado | Crescente | Notificações, webhooks |
none() | 1 | - | Operações que não podem falhar |
Configuração Global
Defina uma política padrão no application.yml:
sagaweaw:
retry:
default-policy: exponential
max-attempts: 3
initial-delay: 1s
max-delay: 30s
multiplier: 2.0
jitter-factor: 0.1
Steps sem .retry() explícito usarão a política global.
Exemplo Completo
@Override
public void define(SagaBuilder<PaymentContext> builder) {
builder
// API interna: retry rápido
.step("validate")
.invoke(this::validate)
.retry(exponential(3, Duration.ofMillis(100)))
// API externa: retry mais lento
.step("charge-stripe")
.invoke(this::chargeStripe)
.compensate(this::refundStripe)
.retry(exponential()
.maxAttempts(5)
.initialDelay(Duration.ofSeconds(2))
.maxDelay(Duration.ofSeconds(30)))
// Notificação: deve sempre ter sucesso
.step("send-receipt")
.invoke(this::sendReceipt)
.retry(infinite()
.initialDelay(Duration.ofMinutes(1))
.maxDelay(Duration.ofHours(1)))
.build();
}