Pular para o conteúdo principal

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âmetroTipoDescrição
maxAttemptsintNúmero máximo de tentativas
initialDelayDurationDelay 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âmetroTipoDescrição
maxAttemptsintNúmero máximo de tentativas
delayDurationDelay 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íticaTentativasDelayUso
exponential()LimitadoCrescenteAPIs externas, bancos
fixed()LimitadoConstanteOperações simples
infinite()IlimitadoCrescenteNotificaçõ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();
}

Relacionados