Tratar erros em fluxos de trabalho do Step Functions - AWS Step Functions

Tratar erros em fluxos de trabalho do Step Functions

Todos os estados, exceto Pass e Wait, podem encontrar erros de tempo de execução. Erros podem ocorrer por vários motivos, incluindo os seguintes:

  • Problemas de definição da máquina de estado, como um estado de escolha sem uma regra de correspondência

  • Falhas na tarefa, como uma exceção em um perfil do AWS Lambda

  • Problemas transitórios, como eventos de partição de rede

Quando um estado relata um erro, o Step Functions por padrão causa falha na execução inteira da máquina de estado. O Step Functions também tem recursos mais avançados de tratamento de erros. Você pode configurar sua máquina de estado para capturar erros, repetir estados com falha e implementar protocolos de tratamento de erros com facilidade.

Os agentes de captura do Step Functions estão disponíveis para os estados tarefa, paralelo e mapa, mas não para falhas de execução de máquinas de estado de alto nível. Para lidar com as execuções que você prevê que possam falhar, o agente de captura pode tratar o erro ou você pode agrupar essas execuções em fluxos de trabalho secundários para detectar erros no fluxo de trabalho principal. Como alternativa, você pode optar por ouvir os eventos TIMED_OUT dos fluxos de trabalho padrão com um barramento do EventBridge e invocar uma ação para lidar com a falha na execução.

Exemplos práticos para tratar erros

Para implantar um exemplo de um fluxo de trabalho que inclua o tratamento de erros, consulte o tutorial Tratar condições de erro em uma máquina de estado do Step Functions deste guia e Tratamento de erros no Workshop AWS Step Functions.

Nomes de erro

O Step Functions identifica erros usando strings que diferenciam maiúsculas e minúsculas, conhecidos como nomes de erro. A Amazon States Language define um conjunto de strings integradas que nomeiam erros conhecidos, todos iniciados com o prefixo States.

Os estados podem relatar erros com outros nomes. No entanto, os nomes de erro não podem começar com o prefixo States..

Verifique se o seu código de produção pode lidar com exceções de serviço do AWS Lambda (Lambda.ServiceException e Lambda.SdkClientException). Para obter mais informações, consulte como Processar exceções transitórias do serviço Lambda nas práticas recomendadas.

States.ALL

Um curinga que corresponde a qualquer nome de erro conhecido.

O tipo de erro States.ALL deve aparecer sozinho em um Catcher e não pode capturar o erro de terminal States.DataLimitExceeded ou os tipos de erro Runtime.

Para obter mais informações, consulte States.DataLimitExceeded e States.Runtime.

States.DataLimitExceeded

Um erro de terminal que não pode ser detectado pelo tipo de erro States.ALL.

Relatado devido às seguintes condições:

  • A saída de um conector é maior do que a cota de tamanho da carga útil.

  • A saída de um estado é maior do que a cota de tamanho da carga útil.

  • Após o processamento de Parameters, a entrada de um estado é maior do que a cota de tamanho da carga útil.

Para ter informações sobre cotas, consulte Cotas de serviço do Step Functions.

States.ExceedToleratedFailureThreshold

Um estado Map falhou porque o número de itens com falha excedeu o limite especificado na definição da máquina de estado. Para obter mais informações, consulte Definir limites de falha para estados de mapa distribuído no Step Functions.

States.HeartbeatTimeout

Um estado Task não conseguiu enviar uma pulsação por um período maior do que o valor HeartbeatSeconds.

HeartbeatTimeout só está disponível nos campos Catch e Retry.

States.Http.Socket

Ocorre quando uma tarefa HTTP expira após 60 segundos. Consulte Cotas relacionadas à tarefa HTTP.

States.ItemReaderFailed

Um estado Map falhou porque não pôde ler na origem do item especificada no campo ItemReader. Para obter mais informações, consulte ItemReader (mapa).

States.Permissions

Um estado Task falhou porque tinha privilégios insuficientes para executar o código especificado.

States.ResultWriterFailed

Um estado Map falhou porque não conseguiu gravar os resultados no destino especificado no campo ResultWriter. Para obter mais informações, consulte ResultWriter (mapa).

States.Runtime

Uma execução falhou devido a alguma exceção que não pôde ser processada. Muitas vezes, isso é causado por erros em tempo de execução, como tentar aplicar InputPath ou OutputPath em uma carga útil JSON nula. Um erro States.Runtime não é recuperável e sempre fará com que a execução falhe. Uma repetição ou uma captura em States.ALL não detectará erros States.Runtime.

States.TaskFailed

Um estado Task falhou durante a execução. Quando usado em uma repetição ou uma captura, States.TaskFailed atua como um curinga que corresponde a qualquer nome de erro conhecido, exceto States.Timeout.

States.Timeout

Relatado quando um estado Task é executado por mais tempo que o valor TimeoutSeconds ou não conseguiu enviar uma pulsação por um período maior que o valor HeartbeatSeconds.

Se uma máquina de estado aninhada lançar um States.Timeout, o principal receberá um erro States.TaskedFailed.

Um erro States.Timeout também é relatado quando a execução de uma máquina de estado inteira é executada por mais tempo do que o valor TimeoutSeconds especificado.

nota

Historicamente, erros não tratados em runtimes do Lambda eram relatados somente como Lambda.Unknown. Em runtimes mais recentes, os tempos limite são relatados como Sandbox.Timedout na saída de erro.

Quando o Lambda excede o número máximo de invocações, o erro relatado será Lambda.TooManyRequestsException.

Corresponde em Lambda.Unknown, Sandbox.Timedout e States.TaskFailed para tratar possíveis erros. Você também pode usar States.ALL, mas deve estar sozinho e no final da lista.

Para ter mais informações sobre os erros Handled e Unhandled do Lambda, consulte FunctionError no Guia do desenvolvedor do AWS Lambda.

Repetir após um erro

Os estados Task, Parallel e Map podem ter um campo denominado Retry, cujo valor deve ser uma matriz de objetos conhecidos como agentes de repetição. Um agente de repetição individual representa determinado número de novas tentativas, geralmente em intervalos de tempo crescentes.

Quando um desses estados relata um erro e há um campo Retry, o Step Functions examina os agentes de repetição na ordem listada na matriz. Quando o nome do erro aparece no valor do campo ErrorEquals de um agente de repetição, a máquina de estado faz repetições, conforme definido no campo Retry.

Se a execução de redriven executar novamente Estado de tarefa do fluxo de trabalho, Estado paralelo do fluxo de trabalho ou um estado de mapa em linha, para o qual você tenha definido repetições, a contagem de repetições para esses estados será redefinida como 0 para possibilitar o número máximo de tentativas em redrive. Para uma execução redriven, você pode monitorar tentativas individuais desses estados usando o console. Para obter mais informações, consulte Repetir o comportamento das execuções redriven em Reiniciar as execuções da máquina de estado com redrive no Step Functions.

Um retrier contém os seguintes campos:

ErrorEquals (obrigatório)

Uma matriz não vazia de strings que correspondem a Nomes de erro. Quando um estado relata um erro, o Step Functions examina os agentes de repetição. Quando o nome do erro é exibido na matriz, ele implementa a política de novas tentativas descrita nesse retrier.

IntervalSeconds (opcional)

Um inteiro positivo que representa o número de segundos antes da primeira tentativa nova (por padrão, 1). IntervalSeconds tem um valor máximo de 99999999.

MaxAttempts (opcional)

Um inteiro positivo que representa o número máximo de tentativas novas (por padrão, 3). Se o erro voltar a ocorrer mais vezes do que o especificado, as novas tentativas são interrompidas e o tratamento de erro normal é retomado. Um valor de 0 especifica que o erro nunca será repetido. MaxAttempts tem um valor máximo de 99999999.

BackoffRate (opcional)

O multiplicador pelo qual o intervalo de novas tentativas indicado por IntervalSeconds aumenta após cada nova tentativa. Por padrão, o valor BackoffRate aumenta em 2.0.

Por exemplo, digamos que IntervalSeconds seja 3, MaxAttempts seja 3 e BackoffRate seja 2. A primeira nova tentativa ocorrerá três segundos após a ocorrência do erro. A segunda nova tentativa ocorrerá seis segundos após a primeira. Enquanto a terceira nova tentativa ocorrerá 12 segundos após a segunda.

MaxDelaySeconds (opcional)

Um número inteiro positivo que define o valor máximo, em segundos, até o qual um intervalo de repetição pode aumentar. É útil usar esse campo com o campo BackoffRate. O valor especificado nesse campo limita os tempos de espera exponenciais resultantes do multiplicador da taxa de recuo aplicado a cada tentativa consecutiva de repetição. É necessário especificar um valor maior do que 0 e menor do que 31622401 para MaxDelaySeconds.

Se esse valor não for especificado, o Step Functions não limitará o tempo de espera entre tentativas de repetição.

JitterStrategy (opcional)

Uma string que determina se é necessário ou não incluir instabilidade nos tempos de espera entre tentativas consecutivas de repetição. A oscilação reduz as tentativas simultâneas de repetição distribuindo-as em um intervalo de atraso aleatório. Essa string aceita FULL ou NONE como valores. O valor padrão é NONE.

Por exemplo, digamos que você tenha definido MaxAttempts como 3, IntervalSeconds como 2 e BackoffRate como 2. A primeira nova tentativa de repetição ocorrerá dois segundos após a ocorrência do erro. A segunda repetição ocorrerá quatro segundos após a primeira e a terceira ocorrerá oito segundos após a segunda. Se você definir JitterStrategy como FULL, o primeiro intervalo de repetição será randomizado entre 0 e 2 segundos, o segundo será randomizado entre 0 e 4 segundos e o terceiro será randomizado entre 0 e 8 segundos.

nota

As novas tentativas são tratadas como transições de estado. Para ver informações sobre como as transições de estado afetam o faturamento, consulte Preços do Step Functions.

Exemplos de campo de repetição

Esta seção inclui os exemplos de campo Retry a seguir.

Exemplo 1: repetir com BackoffRate

O exemplo a seguir de uma Retry faz duas tentativas de repetição. A primeira ocorre depois de uma espera de três segundos. Com base na BackoffRate especificada, o Step Functions aumenta o intervalo entre cada repetição até que o número máximo de tentativas de repetição seja atingido. No exemplo a seguir, a segunda tentativa começa depois de uma espera de três segundos após a primeira repetição.

"Retry": [ { "ErrorEquals": [ "States.Timeout" ], "IntervalSeconds": 3, "MaxAttempts": 2, "BackoffRate": 1 } ]
Exemplo 2: repetir com MaxDelaySeconds

O exemplo a seguir faz três tentativas de repetição e limita o tempo de espera resultante de BackoffRate em 5 segundos. A primeira repetição ocorre depois de uma espera de três segundos. A segunda e a terceira tentativas de repetição ocorrem após uma espera de cinco segundos após a tentativa de repetição anterior, devido ao limite máximo de tempo de espera definido por MaxDelaySeconds.

"Retry": [ { "ErrorEquals": [ "States.Timeout" ], "IntervalSeconds": 3, "MaxAttempts": 3, "BackoffRate":2, "MaxDelaySeconds": 5, "JitterStrategy": "FULL" } ]

Sem MaxDelaySeconds, a segunda tentativa ocorreria seis segundos após a primeira tentativa, e a terceira ocorreria 12 segundos após a segunda tentativa.

Exemplo 3: repetir todos os erros, exceto States.Timeout

O nome reservado States.ALL que aparece no campo ErrorEquals de um retrier é um curinga que corresponde a qualquer nome de erro. Ele deve aparecer sozinho na matriz ErrorEquals e também no último retrier na matriz Retry. O nome States.TaskFailed também atua como um curinga e corresponde a qualquer erro, exceto States.Timeout.

O exemplo de campo Retry a seguir repete qualquer erro, exceto States.Timeout.

"Retry": [ { "ErrorEquals": [ "States.Timeout" ], "MaxAttempts": 0 }, { "ErrorEquals": [ "States.ALL" ] } ]
Exemplo 4: cenário complexo de repetição

Parâmetros de um retrier em todas as visitas ao retrier no contexto de uma única execução de estado.

Considere o seguinte estado Task.

"X": { "Type": "Task", "Resource": "arn:aws:states:region:123456789012:task:X", "Next": "Y", "Retry": [ { "ErrorEquals": [ "ErrorA", "ErrorB" ], "IntervalSeconds": 1, "BackoffRate": 2.0, "MaxAttempts": 2 }, { "ErrorEquals": [ "ErrorC" ], "IntervalSeconds": 5 } ], "Catch": [ { "ErrorEquals": [ "States.ALL" ], "Next": "Z" } ] }

Essa tarefa falha quatro vezes sucessivas, produzindo estes nomes de erro: ErrorA, ErrorB, ErrorC e ErrorB. O seguinte ocorre em consequência disso:

  • Os dois primeiros erros correspondem ao primeiro agente de repetição e provocam esperas de um e dois segundos.

  • O terceiro erro corresponde ao segundo agente de repetição e provoca uma espera de cinco segundos.

  • O quarto erro também corresponde ao primeiro agente de repetição. No entanto, ele já atingiu o máximo de duas repetições (MaxAttempts) para esse erro específico. Portanto, esse agente de repetição falha e a execução redireciona o fluxo de trabalho para o estado Z por meio do campo Catch.

Estados de fallback

Os estados Task, Map e Parallel podem ter um campo denominado Catch. O valor desse campo deve ser uma matriz de objetos, conhecidos como catchers.

Um catcher contém os campos a seguir.

ErrorEquals (obrigatório)

Uma matriz não vazia de strings que correspondem a nomes de erros, especificados exatamente como aparecem no campo do retrier de mesmo nome.

Next (obrigatório)

Uma string que deve corresponder exatamente a um dos nomes de estado da máquina de estado.

ResultPath (JSONPath, opcional)

Um caminho que determina qual entrada o coletor envia ao estado especificado no campo Next.

Quando um estado relata um erro e não existe nenhum campo Retry ou as repetições não conseguem resolver o erro, o Step Functions examina os coletores na ordem listada na matriz. Quando o nome do erro é exibido no valor do campo ErrorEquals de um catcher, a máquina de estado muda para o estado denominado no campo Next.

O nome reservado States.ALL que aparece em um campo ErrorEquals do catcher é um curinga que corresponde a qualquer nome de erro. Ele deve aparecer sozinho na matriz ErrorEquals e também no último catcher na matriz Catch. O nome States.TaskFailed também atua como um curinga e corresponde a qualquer erro, exceto States.Timeout.

O exemplo a seguir de um campo Catch muda para o estado denominado RecoveryState quando uma função do Lambda gera uma exceção Java não tratada. Do contrário, o campo muda para o estado EndState.

"Catch": [ { "ErrorEquals": [ "java.lang.Exception" ], "ResultPath": "$.error-info", "Next": "RecoveryState" }, { "ErrorEquals": [ "States.ALL" ], "Next": "EndState" } ]
Quantos erros um agente de captura pode detectar?

Cada agente de captura pode especificar vários erros para tratamento.

Error output (Saída de erro)

Quando o Step Functions muda para o estado especificado em um nome de captura, o objeto normalmente contém o campo Cause. O valor desse campo é uma descrição de erro humanamente. Esse objeto é conhecido como saída de erro.

No exemplo anterior do JSONPath, o primeiro agente de captura contém um campo ResultPath. Ele funciona de modo semelhante a um campo ResultPath em um nível superior do estado, o que resulta em duas possibilidades:

  • Capturar os resultados de execução do estado e substituir uma parte ou toda a entrada do estado.

  • Pegar os resultados e os adicionar à entrada. No caso de um erro tratado por um agente de captura, o resultado de execução do estado é a saída de erro.

Portanto, no exemplo, o primeiro agente de captura adiciona a saída de erro à entrada como um campo chamado error-info caso ainda não haja um campo com esse nome na entrada. Depois, o agente de captura envia toda a entrada a RecoveryState. Em relação ao segundo agente de captura, a saída de erro substitui a entrada e o agente de captura só envia a saída de erro a EndState.

Em fluxos de trabalho JSONPath, se você não especificar o campo ResultPath, ele usará $ como padrão, que seleciona e substitui a entrada completa.

Quando um estado tem os campos Retry e Catch, o Step Functions usa primeiro qualquer agente de repetição apropriado. Se a política de repetição não solucionar o erro, o Step Functions aplicará a transição correspondente do agente de captura.

Causar cargas úteis e integrações de serviços

Um agente de captura exibe uma carga útil de string como saída. Ao trabalhar com integrações de serviços, como Amazon Athena ou AWS CodeBuild, talvez você queira converter a string Cause em JSON. O exemplo a seguir de um estado Pass com funções intrínsecas mostra como converter uma string Cause em JSON.

"Handle escaped JSON with JSONtoString": { "Type": "Pass", "Parameters": { "Cause.$": "States.StringToJson($.Cause)" }, "Next": "Pass State with Pass Processing" },

Exemplos de máquina de estado usando repetição e captura

As máquinas de estado definidas nos exemplos a seguir presumem que existem duas funções do Lambda: uma que sempre falha e uma que aguarda tempo suficiente para permitir que haja um tempo limite definido na máquina de estado.

Essa é uma definição de função do Lambda Node.js que sempre falha, retornando a mensagem error. Nos exemplos de máquina de estado a seguir, essa função do Lambda é denominada FailFunction. Para ter mais informações sobre como criar uma função do Lambda, consulte a seção Etapa 1: criar uma função do Lambda.

exports.handler = (event, context, callback) => { callback("error"); };

Essa é uma definição de função do Lambda Node.Js que permanece desativada por dez segundos. Nos exemplos de máquina de estado a seguir, essa função do Lambda é denominada sleep10.

exports.handler = (event, context, callback) => { setTimeout(function(){ }, 11000); };
Configurações de tempo limite da função

Ao criar a função do Lambda para os exemplos, defina o valor Timeout nas configurações avançadas para 11 segundos.

Tratar uma falha usando repetição

Essa máquina de estado usa um campo Retry para tentar novamente uma função que falha e gera o nome de erro HandledError. Ela repete essa função duas vezes com um recuo exponencial entre as repetições.

{ "Comment": "A Hello World example invoking Lambda function", "StartAt": "HelloWorld", "States": { "HelloWorld": { "Type": "Task", "Resource": "arn:aws:lambda:region:123456789012:function:FailFunction", "Retry": [ { "ErrorEquals": ["HandledError"], "IntervalSeconds": 1, "MaxAttempts": 2, "BackoffRate": 2.0 } ], "End": true } } }

Essa variante usa o código de erro predefinido States.TaskFailed, que corresponde a qualquer erro gerado por uma função do Lambda.

{ "Comment": "Hello World example which invokes a AWS Lambda function", "StartAt": "HelloWorld", "States": { "HelloWorld": { "Type": "Task", "Resource": "arn:aws:lambda:region:123456789012:function:FailFunction", "Retry": [ { "ErrorEquals": ["States.TaskFailed"], "IntervalSeconds": 1, "MaxAttempts": 2, "BackoffRate": 2.0 } ], "End": true } } }
Práticas recomendadas para lidar com exceções do Lambda

As tarefas que fazem referência a uma função do Lambda devem lidar com exceções do serviço. Para obter mais informações, consulte Processar exceções transitórias do serviço Lambda nas práticas recomendadas.

Tratar uma falha usando captura

Este exemplo usa um campo Catch. Quando uma função do Lambda gera um erro, ele é detectado e a máquina de estado muda para o estado fallback.

{ "Comment": "Hello World example which invokes a AWS Lambda function", "StartAt": "HelloWorld", "States": { "HelloWorld": { "Type": "Task", "Resource": "arn:aws:lambda:region:123456789012:function:FailFunction", "Catch": [ { "ErrorEquals": ["HandledError"], "Next": "fallback" } ], "End": true }, "fallback": { "Type": "Pass", "Result": "Hello, AWS Step Functions!", "End": true } } }

Essa variante usa o código de erro predefinido States.TaskFailed, que corresponde a qualquer erro gerado por uma função do Lambda.

{ "Comment": "Hello World example which invokes a AWS Lambda function", "StartAt": "HelloWorld", "States": { "HelloWorld": { "Type": "Task", "Resource": "arn:aws:lambda:region:123456789012:function:FailFunction", "Catch": [ { "ErrorEquals": ["States.TaskFailed"], "Next": "fallback" } ], "End": true }, "fallback": { "Type": "Pass", "Result": "Hello, AWS Step Functions!", "End": true } } }

Tratar um tempo limite usando repetição

Essa máquina de estado usa um campo Retry para repetir um estado Task que atinge o tempo limite, com base no valor de tempo limite especificado em TimeoutSeconds. O Step Functions repete a invocação da função do Lambda nesse estado Task duas outras vezes, com recuo exponencial entre as repetições.

{ "Comment": "Hello World example which invokes a AWS Lambda function", "StartAt": "HelloWorld", "States": { "HelloWorld": { "Type": "Task", "Resource": "arn:aws:lambda:region:123456789012:function:sleep10", "TimeoutSeconds": 2, "Retry": [ { "ErrorEquals": ["States.Timeout"], "IntervalSeconds": 1, "MaxAttempts": 2, "BackoffRate": 2.0 } ], "End": true } } }

Tratar um tempo limite usando captura

Este exemplo usa um campo Catch. Quando ocorre um tempo limite, a máquina de estado muda para o estado fallback.

{ "Comment": "Hello World example which invokes a AWS Lambda function", "StartAt": "HelloWorld", "States": { "HelloWorld": { "Type": "Task", "Resource": "arn:aws:lambda:region:123456789012:function:sleep10", "TimeoutSeconds": 2, "Catch": [ { "ErrorEquals": ["States.Timeout"], "Next": "fallback" } ], "End": true }, "fallback": { "Type": "Pass", "Result": "Hello, AWS Step Functions!", "End": true } } }
Preservar a entrada de estado e o erro no JSONPath

No JSONPath, você pode preservar a entrada de estado e o erro usando ResultPath. Consulte Usar ResultPath para incluir o erro e a entrada em um Catch.