Share via


Lidando com erros nas Funções Duráveis (Azure Functions)

As orquestrações de Funções Duráveis são implementadas no código e podem usar os recursos internos de tratamento de erros da linguagem de programação. Não há novos conceitos que você precise aprender para adicionar a compensação e o tratamento de erro às suas orquestrações. No entanto, há alguns comportamentos a que você deve estar atento.

Observação

A versão 4 do modelo de programação Node.js para o Azure Functions está em disponibilidade geral. O novo modelo v4 é projetado para oferecer uma experiência mais flexível e intuitiva para desenvolvedores de JavaScript e TypeScript. Saiba mais sobre as diferenças entre v3 e v4 na guia de migração.

Nos trechos de código a seguir, o JavaScript (PM4) denota o modelo de programação V4, a nova experiência.

Erros em funções de atividade

Qualquer exceção que é lançada em uma função de atividade sofre vai realizar marshaling de volta para a função de orquestrador e é lançada como um FunctionFailedException. Você pode escrever o código de compensação e tratamento de erro que atenda às suas necessidades na função de orquestrador.

Por exemplo, considere a seguinte função de orquestrador, que transfere fundos de uma conta para outra:

[FunctionName("TransferFunds")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var transferDetails = context.GetInput<TransferOperation>();

    await context.CallActivityAsync("DebitAccount",
        new
        {
            Account = transferDetails.SourceAccount,
            Amount = transferDetails.Amount
        });

    try
    {
        await context.CallActivityAsync("CreditAccount",
            new
            {
                Account = transferDetails.DestinationAccount,
                Amount = transferDetails.Amount
            });
    }
    catch (Exception)
    {
        // Refund the source account.
        // Another try/catch could be used here based on the needs of the application.
        await context.CallActivityAsync("CreditAccount",
            new
            {
                Account = transferDetails.SourceAccount,
                Amount = transferDetails.Amount
            });
    }
}

Observação

O exemplo de C# anterior é para o Durable Functions 2.x. No Durable Functions 1.x, use DurableOrchestrationContext em vez de IDurableOrchestrationContext. Para obter mais informações sobre as diferenças entre versões, confira o artigo Versões do Durable Functions.

Se a primeira chamada de função CreditAccount falhar, a função de orquestrador compensará creditando os fundos de volta à conta de origem.

Repetição automática em caso de falha

Quando chama funções de atividade ou funções de suborquestração, você pode especificar uma política de repetição automática. O exemplo a seguir tenta chamar uma função até três vezes e espera cinco segundos entre cada repetição:

[FunctionName("TimerOrchestratorWithRetry")]
public static async Task Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var retryOptions = new RetryOptions(
        firstRetryInterval: TimeSpan.FromSeconds(5),
        maxNumberOfAttempts: 3);

    await context.CallActivityWithRetryAsync("FlakyFunction", retryOptions, null);

    // ...
}

Observação

O exemplo de C# anterior é para o Durable Functions 2.x. No Durable Functions 1.x, use DurableOrchestrationContext em vez de IDurableOrchestrationContext. Para obter mais informações sobre as diferenças entre versões, confira o artigo Versões do Durable Functions.

A chamada de função de atividade no exemplo anterior recebe um parâmetro para configurar uma política de nova tentativa automática. Há várias opções para personalizar a política de repetição automática:

  • Núm. máximo de tentativas: o número máximo de tentativas de repetição. Se definido como 1, não haverá nenhuma repetição.
  • Primeiro intervalo de repetição: o tempo de espera antes de fazer a primeira tentativa.
  • Coeficiente de retirada: o coeficiente usado para determinar a taxa de aumento de retirada. O valor padrão é 1.
  • Intervalo máx. de repetição: o tempo máximo de espera entre tentativas de repetição.
  • Tempo limite de repetição: o tempo máximo a ser dedicado às novas tentativas. O comportamento padrão é repetir indefinidamente.

Manipuladores de repetição personalizados

Ao usar o .NET ou o Java, você também tem a opção de implementar manipuladores de repetição no código. Isso é útil quando políticas de repetição declarativas não são expressivas o suficiente. Para linguagens que não dão suporte a manipuladores de repetição personalizados, você ainda tem a opção de implementar políticas de repetição usando loops, tratamento de exceção e temporizadores para injetar atrasos entre novas tentativas.

RetryOptions retryOptions = new RetryOptions(
    firstRetryInterval: TimeSpan.FromSeconds(5),
    maxNumberOfAttempts: int.MaxValue)
    {
        Handle = exception =>
        {
            // True to handle and try again, false to not handle and throw.
            if (exception is TaskFailedException failure)
            {
                // Exceptions from TaskActivities are always this type. Inspect the
                // inner Exception to get more details.
            }

            return false;
        };
    }

await ctx.CallActivityWithRetryAsync("FlakeyActivity", retryOptions, null);

Tempos limite de função

Talvez você queira abandonar uma chamada de função dentro de uma função de orquestrador se ela estiver demorando muito para ser concluída. No momento, o modo adequado de fazer isso é criar um temporizador durável com “qualquer” seletor de tarefa, conforme mostrado no exemplo a seguir:

[FunctionName("TimerOrchestrator")]
public static async Task<bool> Run([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    TimeSpan timeout = TimeSpan.FromSeconds(30);
    DateTime deadline = context.CurrentUtcDateTime.Add(timeout);

    using (var cts = new CancellationTokenSource())
    {
        Task activityTask = context.CallActivityAsync("FlakyFunction");
        Task timeoutTask = context.CreateTimer(deadline, cts.Token);

        Task winner = await Task.WhenAny(activityTask, timeoutTask);
        if (winner == activityTask)
        {
            // success case
            cts.Cancel();
            return true;
        }
        else
        {
            // timeout case
            return false;
        }
    }
}

Observação

O exemplo de C# anterior é para o Durable Functions 2.x. No Durable Functions 1.x, use DurableOrchestrationContext em vez de IDurableOrchestrationContext. Para obter mais informações sobre as diferenças entre versões, confira o artigo Versões do Durable Functions.

Observação

Esse mecanismo não encerra a execução de funções de atividade em andamento. Em vez disso, ele simplesmente permite que a função de orquestrador ignore o resultado e prossiga. Para mais informações, confira a documentação dos Medidores de tempo.

Exceções sem tratamento

Se uma função de orquestrador falhar com uma exceção sem tratamento, os detalhes da exceção serão registrados e a instância será concluída com um status Failed.

Próximas etapas