Partilhar via


Tratamento de erros em funções duráveis (Azure Functions)

As orquestrações de funções duráveis são implementadas em código e podem usar os recursos internos de tratamento de erros da linguagem de programação. Realmente não há novos conceitos que você precise aprender para adicionar tratamento de erros e compensação em suas orquestrações. No entanto, existem alguns comportamentos que você deve estar ciente.

Nota

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

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

Erros nas funções de atividade

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

Por exemplo, considere a seguinte função orquestradora 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
            });
    }
}

Nota

Os exemplos anteriores de C# são para Durable Functions 2.x. Para Durable Functions 1.x, você deve usar DurableOrchestrationContext em vez de IDurableOrchestrationContext. Para obter mais informações sobre as diferenças entre versões, consulte o artigo Durable Functions versions .

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

Repetição automática em caso de falha

Ao chamar 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 aguarda 5 segundos entre cada nova tentativa:

[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);

    // ...
}

Nota

Os exemplos anteriores de C# são para Durable Functions 2.x. Para Durable Functions 1.x, você deve usar DurableOrchestrationContext em vez de IDurableOrchestrationContext. Para obter mais informações sobre as diferenças entre versões, consulte o artigo Durable Functions versions .

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

  • Número máximo de tentativas: o número máximo de tentativas. Se definido como 1, não haverá nova tentativa.
  • Primeiro intervalo de tentativas: o tempo de espera antes da primeira tentativa.
  • Coeficiente de backoff: O coeficiente usado para determinar a taxa de aumento de backoff. O padrão é 1.
  • Intervalo máximo de repetição: o tempo máximo de espera entre as tentativas de repetição.
  • Tempo limite de repetição: a quantidade máxima de tempo para fazer tentativas. O comportamento padrão é tentar novamente indefinidamente.

Manipuladores de repetição personalizados

Ao usar o .NET ou Java, você também tem a opção de implementar manipuladores de repetição no código. Isso é útil quando as políticas declarativas de repetição não são expressivas o suficiente. Para idiomas que não oferecem 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ções e temporizadores para injetar atrasos entre 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

Você pode querer abandonar uma chamada de função dentro de uma função orchestrator se ela estiver demorando muito para ser concluída. A maneira correta de fazer isso hoje é criando um temporizador durável com um seletor de tarefas "qualquer", como 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;
        }
    }
}

Nota

Os exemplos anteriores de C# são para Durable Functions 2.x. Para Durable Functions 1.x, você deve usar DurableOrchestrationContext em vez de IDurableOrchestrationContext. Para obter mais informações sobre as diferenças entre versões, consulte o artigo Durable Functions versions .

Nota

Na verdade, esse mecanismo não encerra a execução da função de atividade em andamento. Em vez disso, ele simplesmente permite que a função orquestradora ignore o resultado e siga em frente. Para obter mais informações, consulte a documentação dos temporizadores .

Exceções não processadas

Se uma função orchestrator falhar com uma exceção não tratada, os detalhes da exceção serão registrados e a instância será concluída com um Failed status.

Próximos passos