Lidar com erros no Durable Functions (Funções do Azure)

As orquestrações da Durable Function são implementadas em código e podem utilizar as funcionalidades incorporadas de processamento de erros da linguagem de programação. Não existem novos conceitos que precise de aprender a adicionar processamento de erros e compensação às suas orquestrações. No entanto, existem alguns comportamentos que deve ter em atenção.

Nota

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

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

Erros nas funções de atividade

Qualquer exceção que seja emitida numa função de atividade é devolvida à função do orquestrador e lançada como um FunctionFailedException. Pode escrever o processamento de erros e o código de compensação que se adequa às suas necessidades na função orchestrator.

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

Nota

Os exemplos anteriores de C# destinam-se a Durable Functions 2.x. Para Durable Functions 1.x, tem de utilizar DurableOrchestrationContext em vez de IDurableOrchestrationContext. Para obter mais informações sobre as diferenças entre versões, consulte o artigo Durable Functions versões.

Se a primeira chamada da função CreditAccount falhar, a função orchestrator compensa ao creditar os fundos novamente na conta de origem.

Repetição automática de falhas

Quando chama funções de atividade ou funções de sub-orquestração, pode especificar uma política de repetição automática. O exemplo seguinte tenta chamar uma função até três vezes e aguarda 5 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);

    // ...
}

Nota

Os exemplos anteriores de C# destinam-se a Durable Functions 2.x. Para Durable Functions 1.x, tem de utilizar DurableOrchestrationContext em vez de IDurableOrchestrationContext. Para obter mais informações sobre as diferenças entre versões, consulte o artigo Durable Functions versões.

A chamada da função de atividade no exemplo anterior utiliza um parâmetro para configurar uma política de repetição automática. Existem 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 estiver definido como 1, não haverá repetição.
  • Primeiro intervalo de repetição: a quantidade de tempo a aguardar antes da primeira tentativa de repetição.
  • Coeficiente de backoff: o coeficiente utilizado para determinar a taxa de aumento do backoff. A predefinição é 1.
  • Intervalo máximo de repetição: a quantidade máxima de tempo a aguardar entre tentativas de repetição.
  • Tempo limite de repetição: a quantidade máxima de tempo a passar a fazer repetições. O comportamento predefinido é tentar novamente indefinidamente.

Processadores de repetição personalizados

Ao utilizar o .NET ou Java, também tem a opção de implementar processadores de repetição no código. Isto é útil quando as políticas declarativas de repetição não são suficientemente expressivas. Para idiomas que não suportam processadores de repetição personalizados, ainda tem a opção de implementar políticas de repetição com ciclos, processamento de exceções e temporizadores para injetar atrasos entre repetições.

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 da função

Poderá querer abandonar uma chamada de função dentro de uma função de orquestrador se estiver a demorar demasiado tempo a concluir. A forma adequada de o fazer atualmente é criar um temporizador durável com um seletor de tarefas "qualquer", como no exemplo seguinte:

[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# destinam-se a Durable Functions 2.x. Para Durable Functions 1.x, tem de utilizar DurableOrchestrationContext em vez de IDurableOrchestrationContext. Para obter mais informações sobre as diferenças entre versões, consulte o artigo Durable Functions versões.

Nota

Este mecanismo não termina efetivamente a execução da função de atividade em curso. Em vez disso, permite simplesmente que a função do orquestrador ignore o resultado e avance. Para obter mais informações, veja a documentação temporizadores .

Exceções não processadas

Se uma função do orquestrador falhar com uma exceção não processada, os detalhes da exceção serão registados e a instância será concluída com um Failed estado.

Passos seguintes