Novas tentativas para funções duráveis do Lambda - AWS Lambda

Novas tentativas para funções duráveis do Lambda

As funções duráveis fornecem recursos de novas tentativas automáticas que tornam suas aplicações resilientes a falhas transitórias. O SDK lida com novas tentativas em dois níveis: novas tentativas de etapas para falhas na lógica de negócios e novas tentativas de backend em caso de falhas de infraestrutura.

Novas tentativas de etapa

Quando ocorre uma exceção não detectada em uma etapa, o SDK faz uma nova tentativa da etapa automaticamente com base na estratégia de novas tentativas configurada. As novas tentativas de etapas são operações com pontos de verificação que permitem que o SDK suspenda a execução e continue posteriormente sem perder o andamento.

Comportamento de novas tentativas de etapa

A tabela a seguir descreve como o SDK lida com exceções em etapas:

Cenário O que acontece Medição de impacto
Exceção em etapa com novas tentativas restantes O SDK cria um ponto de verificação para a nova tentativa e suspende a função. Na próxima invocação, a etapa sofre nova tentativa com o retardo de recuo configurado. 1 operação + tamanho da carga útil de erro
Exceção em etapa sem novas tentativas restantes A etapa falha e emite uma exceção. Se o seu código do manipulador não capturar essa exceção, toda a execução falhará. 1 operação + tamanho da carga útil de erro

Quando uma etapa precisa ser repetida, o SDK verifica o estado de novas tentativas e sai da invocação do Lambda se nenhum outro trabalho estiver em execução. Isso permite que o SDK implemente retardos de recuo sem consumir recursos computacionais. A função é retomada automaticamente após o período de recuo.

Configuração de estratégias de novas tentativas de etapas

Configure estratégias de novas tentativas para controlar como as etapas tratam as falhas. É possível especificar o máximo de tentativas, os intervalos de recuo e as condições para novas tentativas.

Recuo exponencial com o máximo de tentativas:

TypeScript
const result = await context.step('call-api', async () => { const response = await fetch('https://api.example.com/data'); if (!response.ok) throw new Error(`API error: ${response.status}`); return await response.json(); }, { retryStrategy: (error, attemptCount) => { if (attemptCount >= 5) { return { shouldRetry: false }; } // Exponential backoff: 2s, 4s, 8s, 16s, 32s (capped at 300s) const delay = Math.min(2 * Math.pow(2, attemptCount - 1), 300); return { shouldRetry: true, delay: { seconds: delay } }; } });
Python
def retry_strategy(error, attempt_count): if attempt_count >= 5: return {'should_retry': False} # Exponential backoff: 2s, 4s, 8s, 16s, 32s (capped at 300s) delay = min(2 * (2 ** (attempt_count - 1)), 300) return {'should_retry': True, 'delay': delay} result = context.step( lambda _: call_external_api(), name='call-api', config=StepConfig(retry_strategy=retry_strategy) )

Recuo com intervalo fixo:

TypeScript
const orders = await context.step('query-orders', async () => { return await queryDatabase(event.userId); }, { retryStrategy: (error, attemptCount) => { if (attemptCount >= 3) { return { shouldRetry: false }; } return { shouldRetry: true, delay: { seconds: 5 } }; } });
Python
def retry_strategy(error, attempt_count): if attempt_count >= 3: return {'should_retry': False} return {'should_retry': True, 'delay': 5} orders = context.step( lambda _: query_database(event['userId']), name='query-orders', config=StepConfig(retry_strategy=retry_strategy) )

Nova tentativa condicional (tentar novamente somente erros específicos):

TypeScript
const result = await context.step('call-rate-limited-api', async () => { const response = await fetch('https://api.example.com/data'); if (response.status === 429) throw new Error('RATE_LIMIT'); if (response.status === 504) throw new Error('TIMEOUT'); if (!response.ok) throw new Error(`API_ERROR_${response.status}`); return await response.json(); }, { retryStrategy: (error, attemptCount) => { // Only retry rate limits and timeouts const isRetryable = error.message === 'RATE_LIMIT' || error.message === 'TIMEOUT'; if (!isRetryable || attemptCount >= 3) { return { shouldRetry: false }; } // Exponential backoff: 1s, 2s, 4s (capped at 30s) const delay = Math.min(Math.pow(2, attemptCount - 1), 30); return { shouldRetry: true, delay: { seconds: delay } }; } });
Python
def retry_strategy(error, attempt_count): # Only retry rate limits and timeouts is_retryable = str(error) in ['RATE_LIMIT', 'TIMEOUT'] if not is_retryable or attempt_count >= 3: return {'should_retry': False} # Exponential backoff: 1s, 2s, 4s (capped at 30s) delay = min(2 ** (attempt_count - 1), 30) return {'should_retry': True, 'delay': delay} result = context.step( lambda _: call_rate_limited_api(), name='call-rate-limited-api', config=StepConfig(retry_strategy=retry_strategy) )

Desativar novas tentativas:

TypeScript
const isDuplicate = await context.step('check-duplicate', async () => { return await checkIfOrderExists(event.orderId); }, { retryStrategy: () => ({ shouldRetry: false }) });
Python
is_duplicate = context.step( lambda _: check_if_order_exists(event['orderId']), name='check-duplicate', config=StepConfig( retry_strategy=lambda error, attempt: {'should_retry': False} ) )

Quando a estratégia de novas tentativas retorna shouldRetry: false, a etapa falha imediatamente sem novas tentativas. Use isso para operações que não devam ser repetidas, como verificações de idempotência ou operações com efeitos colaterais que não possam ser repetidos com segurança.

Exceções fora das etapas

Quando ocorre uma exceção não detectada no código do manipulador, mas fora de qualquer etapa, o SDK marca a execução como com falha. Isso garante que os erros na lógica da aplicação sejam capturados e relatados adequadamente.

Cenário O que acontece Medição de impacto
Exceção no código do manipulador fora de qualquer etapa O SDK marca a execução como COM FALHA e retorna o erro. A exceção não sofre nova tentativa automaticamente. Tamanho da carga útil de erro

Para habilitar a nova tentativa automática para código propenso a erros, encapsule-o em uma etapa com uma estratégia de nova tentativa. As etapas fornecem uma nova tentativa automática com recuo configurável, enquanto as etapas externas do código falham imediatamente.

Novas tentativas de backend

As novas tentativas de backend ocorrem quando o Lambda encontra falhas de infraestrutura, erros de runtime ou quando o SDK não consegue se comunicar com o serviço de execução durável. O Lambda faz uma nova tentativa dessas falhas automaticamente para garantir que suas funções duráveis possam se recuperar de problemas transitórios de infraestrutura.

Cenários de nova tentativa de backend

O Lambda faz uma nova tentativa da sua função automaticamente quando encontra os cenários a seguir:

  • Erros de serviço internos: quando o Lambda ou o serviço de execução durável retorna um erro 5xx, indicando um problema temporário no serviço.

  • Limitação: quando sua função sofre controle de utilização devido a limites de simultaneidade ou cotas de serviço.

  • Tempos limite: quando o SDK não consegue alcançar o serviço de execução durável dentro do período de tempo limite.

  • Falhas na inicialização da sandbox: quando o Lambda não consegue inicializar o ambiente de execução.

  • Erros de runtime: quando o runtime do Lambda encontra erros fora do seu código de função, como erros de falta de memória ou falhas no processo.

  • Erros de token de ponto de verificação inválido: quando o token de ponto de verificação não é mais válido, normalmente devido a mudanças de estado do lado do serviço.

A tabela a seguir descreve como o SDK trata esses cenários.

Cenário O que acontece Medição de impacto
Erro de runtime fora do manipulador durável (OOM, tempo limite, falha) O Lambda automaticamente faz uma nova tentativa de invocação. O SDK é reproduzido a partir do último ponto de verificação, ignorando as etapas concluídas. Tamanho da carga útil de erro + 1 operação por nova tentativa
Erro de serviço (5xx) ou tempo limite ao chamar as APIs CheckpointDurableExecution / GetDurableExecutionState O Lambda automaticamente faz uma nova tentativa de invocação. O SDK reproduz a partir do último ponto de verificação. Tamanho da carga útil de erro + 1 operação por nova tentativa
Controle de utilização (429) ou token de ponto de verificação inválido ao chamar as APIs CheckpointDurableExecution / GetDurableExecutionState O Lambda automaticamente faz uma nova tentativa de invocação com recuo exponencial. O SDK reproduz a partir do último ponto de verificação. Tamanho da carga útil de erro + 1 operação por nova tentativa
Erro do cliente (4xx, exceto 429 e token inválido) quando as APIs CheckpointDurableExecution / GetDurableExecutionState O SDK marca a execução como COM FALHA. Nenhuma nova tentativa automática ocorre porque o erro indica um problema permanente. Tamanho da carga útil de erro

As novas tentativas de backend usam o recuo exponencial e prosseguem até que a função tenha êxito ou o tempo limite de execução seja atingido. Durante a reprodução, o SDK ignora os pontos de verificação concluídos e continua a execução da última operação com êxito, garantindo que sua função não reexecute o trabalho concluído.

Práticas recomendadas de novas tentativas

Siga estas práticas recomendadas ao configurar estratégias de novas tentativas:

  • Configure estratégias de novas tentativas explícitas: não confie no comportamento padrão de novas tentativas na produção. Configure estratégias de novas tentativas explícitas com o máximo de tentativas e intervalos de recuo apropriados para seu caso de uso.

  • Use novas tentativas condicionais: - implemente a lógica shouldRetry para repetir somente erros transitórios (limites de taxa, tempos limite) e antecipe-se à falha em erros permanentes (falhas de validação, não encontrado).

  • Defina o máximo de tentativas apropriadas: equilíbrio entre resiliência e tempo de execução. Muitas tentativas podem atrasar a detecção de falhas, enquanto poucas podem causar falhas desnecessárias.

  • Use o recuo exponencial: o recuo exponencial reduz a carga nos serviços subsequentes e aumenta a probabilidade de recuperação de falhas transitórias.

  • Encapsule o código propenso a erros em etapas: o código fora das etapas não pode sofrer novas tentativas automaticamente. Encapsule chamadas externas de API, consultas de banco de dados e outras operações sujeitas a erros em etapas com estratégias de novas tentativas.

  • Monitore as métricas de novas tentativas: acompanhe as operações de novas tentativas de etapas e falhas de execução no Amazon CloudWatch para identificar padrões e otimizar estratégias de novas tentativas.