Temporizadores nas Funções Duráveis (Azure Functions)

As Funções Duráveis fornecem temporizadores duráveis para uso em funções de orquestrador para implementar atrasos ou para configurar tempos limite em ações assíncronas. Os temporizadores duráveis devem ser usados em funções de orquestrador em vez de APIs "suspensão" ou "atraso" que podem ser incorporadas ao idioma.

Temporizadores duráveis são tarefas que são criadas usando a API apropriada de "criar temporizador" para o idioma fornecido, conforme mostrado abaixo, e levam um tempo devido ou uma duração como um argumento.

// Put the orchestrator to sleep for 72 hours
DateTime dueTime = context.CurrentUtcDateTime.AddHours(72);
await context.CreateTimer(dueTime, CancellationToken.None);

Ao "aguarda" a tarefa do temporizador, a função de orquestrador ficará em suspensão até o tempo de expiração especificado.

Observação

As orquestrações continuarão processando outros eventos de entrada enquanto aguardam a expiração de uma tarefa de temporizador.

Limitações do temporizador

Ao criar um temporizador que expira às 16h30 UTC, o Durable Task Framework subjacente enfileira uma mensagem que se torna visível apenas às 16h30 UTC. Se o aplicativo de funções for reduzido para zero instâncias enquanto isso, a mensagem de temporizador recém-visível garantirá que o aplicativo de funções seja ativado novamente em uma VM apropriada.

Observação

  • Para aplicativos JavaScript, Python e PowerShell, os temporizadores duráveis são limitados a seis dias. Para contornar essa limitação, você pode usar as APIs de temporizador em um loop while para simular um atraso mais longo. Aplicativos .NET e Java atualizados dão suporte a temporizadores arbitrariamente longos.
  • Dependendo da versão do SDK e do provedor de armazenamento que está sendo usado, temporizadores longos de 6 dias ou mais podem ser implementados internamente usando uma série de temporizadores mais curtos (por exemplo, de durações de 3 dias) até que o tempo de expiração desejado seja atingido. Isso pode ser observado no armazenamento de dados subjacente, mas não afetará o comportamento de orquestração.
  • Não use APIs internas de data/hora para obter a hora atual. Ao calcular uma data futura para um temporizador expirar, sempre use a API de hora atual da função de orquestrador. Para obter mais informações, confira o artigo Restrições de código na função de orquestrador.

Uso para atrasos

O exemplo a seguir ilustra como usar temporizadores duráveis para atrasar a execução. O exemplo emite uma notificação de cobrança todos os dias por 10 dias.

[FunctionName("BillingIssuer")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    for (int i = 0; i < 10; i++)
    {
        DateTime deadline = context.CurrentUtcDateTime.Add(TimeSpan.FromDays(1));
        await context.CreateTimer(deadline, CancellationToken.None);
        await context.CallActivityAsync("SendBillingEvent");
    }
}

Observação

O exemplo de C# anterior tem como destino 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.

Aviso

Evite loops infinitos em funções de orquestrador. Para obter informações sobre como implementar de forma segura e eficiente cenários de loop infinito, consulte Orquestrações eternas.

Uso para tempo limite

Este exemplo ilustra como usar temporizadores duráveis para implementar tempos limite.

[FunctionName("TryGetQuote")]
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("GetQuote");
        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 tem como destino 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.

Aviso

No .NET, JavaScript, Python e PowerShell, você deve cancelar todos os temporizadores duráveis criados se o código não aguardar a conclusão deles. Veja os exemplos acima para saber como cancelar temporizadores pendentes. O Durable Task Framework não altera o status de uma orquestração para "Concluído" até que todas as tarefas pendentes, incluindo tarefas de temporizador duráveis, sejam concluídas ou canceladas.

Esse mecanismo de cancelamento usando o padrão quando qualquer não encerra as execuções da suborquestração nem da função de atividade em andamento. Em vez disso, ele simplesmente permite que a função de orquestrador ignore o resultado e prossiga. Se o seu aplicativo de funções usar o plano de Consumo, você ainda será cobrado pelo tempo e pela memória consumida pela função de atividade abandonada. Por padrão, funções em execução pelo Plano de Consumo têm um tempo limite de cinco minutos. Se esse limite for ultrapassado, o host do Azure Functions será reciclado para interromper toda a execução e evitar uma situação de cobrança sem controle. O tempo limite da função é configurável.

Para obter um exemplo mais detalhado de como implementar tempos limite nas funções do orquestrador, confira o artigo Interação humana e tempos limite – Verificação por telefone.

Próximas etapas