Durable Functions para Fluxos de Trabalho com Estado
Orquestre fluxos de trabalho de longa duração usando padrões de orquestração do Durable Functions (distribuição e agregação, encadeamento, monitoramento) e compreenda como o estado é salvo em pontos de verificação.
Durable Functions para Fluxos de Trabalho com Estado é uma aula grátis de Cloud & IT Cert Prep no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Cloud & IT Cert Prep, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Cloud & IT Cert Prep inclui 4 aulas no total.
Por que usar funções Durable?
As funções comuns do Azure não têm estado — cada invocação é executada de forma independente, sem memória das chamadas anteriores. As funções Durable estendem as funções do Azure com a capacidade de escrever fluxos de trabalho com estado e de longa duração usando código assíncrono comum com async/await. O Durable Task Framework cria automaticamente pontos de verificação do estado no Azure Storage após cada etapa, permitindo que os fluxos de trabalho sobrevivam a reinicializações de servidor, timeouts ou manutenções planejadas e sejam retomados exatamente de onde pararam.
Os três tipos de função
As funções Durable apresentam três tipos de função. Uma função orquestradora coordena o fluxo de trabalho geral — chama funções de atividade e aguarda os resultados usando yield ou await, sem bloquear de fato uma thread. Uma função de atividade executa uma única unidade de trabalho (chamar uma API, gravar em um banco de dados) e é o único local onde devem ocorrer efeitos colaterais. Uma função de entidade mantém pequenas partes do estado durável (contadores, sinalizadores) entre chamadas.
// Client function (HTTP trigger) — starts the orchestration
module.exports = async function (context, req) {
const client = df.getClient(context);
const orderId = req.body.orderId;
const instanceId = await client.startNew('OrderOrchestrator', undefined, { orderId });
return client.createCheckStatusResponse(context.bindingData.req, instanceId);
};O padrão de encadeamento
O padrão de encadeamento executa funções de atividade sequencialmente, passando a saída de uma como entrada para a próxima. A função orquestradora aguarda cada atividade por vez. Se alguma atividade falhar, o fluxo de trabalho será interrompido e poderá ser reiniciado a partir da etapa que falhou. Este é o padrão mais simples de funções Durable e é adequado para fluxos de trabalho em que cada etapa depende do resultado da anterior, como pipelines de processamento de pedidos.
// Orchestrator: chaining pattern
const df = require('durable-functions');
module.exports = df.orchestrator(function* (context) {
const orderId = context.df.getInput().orderId;
const validated = yield context.df.callActivity('ValidateOrder', orderId);
const charged = yield context.df.callActivity('ChargePayment', validated);
const shipped = yield context.df.callActivity('ShipOrder', charged);
return { status: 'shipped', trackingId: shipped.trackingId };
});Padrão Fan-Out / Fan-In
O padrão fan-out/fan-in inicia várias funções de atividade em paralelo e aguarda a conclusão de todas antes de continuar. A função orquestradora inicia todas as tarefas simultaneamente usando callActivity, sem aguardá-las, reúne os objetos de tarefa em uma matriz e, em seguida, usa Task.all(). Isso é muito mais rápido que o processamento sequencial para itens de trabalho independentes, como processar vários arquivos, chamar várias APIs ou executar operações em lote.
// Orchestrator: fan-out / fan-in
module.exports = df.orchestrator(function* (context) {
const items = context.df.getInput().items;
// Fan-out: start all tasks in parallel
const tasks = items.map(item => context.df.callActivity('ProcessItem', item));
// Fan-in: wait for all tasks to complete
const results = yield context.df.Task.all(tasks);
return results;
});O padrão de monitoramento
O padrão de monitoramento consulta um sistema externo em intervalos até que uma condição seja atendida — de modo semelhante a um loop de consulta, mas totalmente durável. A função orquestradora chama uma atividade para verificar o status, aguarda um intervalo configurável usando createTimer e então repete o processo. Como o estado é salvo no armazenamento entre cada consulta, a função orquestradora não consome recursos computacionais enquanto aguarda, sendo muito mais eficiente que uma abordagem baseada em um temporizador em espera.
// Orchestrator: monitor pattern (poll until job completes)
module.exports = df.orchestrator(function* (context) {
const jobId = context.df.getInput().jobId;
const expiry = new Date(context.df.currentUtcDateTime);
expiry.setHours(expiry.getHours() + 24); // 24-hour timeout
while (context.df.currentUtcDateTime < expiry) {
const status = yield context.df.callActivity('GetJobStatus', jobId);
if (status === 'completed') return { jobId, status };
if (status === 'failed') throw new Error('Job failed');
// Wait 30 seconds before next poll
const nextCheck = new Date(context.df.currentUtcDateTime);
nextCheck.setSeconds(nextCheck.getSeconds() + 30);
yield context.df.createTimer(nextCheck);
}
throw new Error('Workflow timed out');
});Padrão de interação humana
O padrão de interação humana pausa uma orquestração e aguarda um evento externo — como a aprovação de um gerente. A função orquestradora usa waitForExternalEvent, que pode aguardar dias ou semanas sem consumir recursos computacionais. Um sistema externo (link de aprovação por e-mail, aplicativo móvel ou webhook) chama a API HTTP das funções Durable para gerar o evento, desbloqueando a orquestração. Combine isso com um temporizador para aplicar um timeout automático e realizar uma escalada caso nenhuma resposta chegue.
// Orchestrator: wait for human approval with timeout
module.exports = df.orchestrator(function* (context) {
const request = context.df.getInput();
yield context.df.callActivity('SendApprovalEmail', request);
const timeout = df.Task.createTimer(context, new Date(Date.now() + 48 * 3600 * 1000));
const approval = context.df.waitForExternalEvent('ApprovalResponse');
const winner = yield context.df.Task.any([approval, timeout]);
if (winner === approval) {
const approved = winner.result;
return approved ? 'Approved' : 'Rejected';
} else {
return 'Timed out — escalated';
}
});Restrições das funções orquestradoras
As funções orquestradoras têm restrições importantes porque podem ser reproduzidas várias vezes a partir do histórico para reconstruir o estado. Elas devem ser determinísticas — nunca use Date.now(), Math.random() nem faça chamadas diretas de E/S. Em vez disso, use context.df.currentUtcDateTime para obter marcações de tempo e chame funções de atividade para toda E/S. O registro de eventos no corpo da função orquestradora produzirá entradas duplicadas durante a reprodução; use funções de atividade para fazer o registro.
// WRONG — non-deterministic, will cause replay bugs
module.exports = df.orchestrator(function* (context) {
const now = new Date(); // Don't use Date()
const rand = Math.random(); // Don't use Math.random()
const data = await fetch('/api'); // Don't make HTTP calls directly
});
// CORRECT
module.exports = df.orchestrator(function* (context) {
const now = context.df.currentUtcDateTime; // OK
const data = yield context.df.callActivity('FetchData', null); // OK
});Gerenciamento de instâncias: status e encerramento
Cada execução de orquestração tem um ID de instância exclusivo que você pode usar para consultar seu status, enviar eventos ou encerrá-la. A API HTTP de gerenciamento das funções Durable fornece endpoints para verificar o status (GET /instances/{id}), enviar eventos (POST /instances/{id}/raiseEvent/{name}) e encerrar (POST /instances/{id}/terminate). Use a vinculação de cliente Durable em suas funções para acessar essas operações programaticamente.
// Client function: check orchestration status
module.exports = async function (context, req) {
const client = df.getClient(context);
const instanceId = req.params.instanceId;
const status = await client.getStatus(instanceId, true, true, true);
return {
status: 200,
body: {
instanceId,
runtimeStatus: status.runtimeStatus,
customStatus: status.customStatus,
output: status.output
}
};
};Back-end de armazenamento e desempenho
As funções Durable armazenam o histórico da orquestração, o estado da instância e as filas de mensagens entre funções em uma conta do Azure Storage (ou em back-ends do Azure SQL/Netherite para maior throughput). Cada ponto de verificação grava dados no Azure Table Storage e no Azure Queue Storage. Em cenários de alto throughput (milhares de orquestrações simultâneas), o back-end de armazenamento Netherite usa o Azure Event Hubs para oferecer desempenho muito superior. Monitore a profundidade da fila de orquestração para detectar gargalos.
// host.json: configure the Durable Task storage provider
{
'version': '2.0',
'extensions': {
'durableTask': {
'hubName': 'MyTaskHub',
'storageProvider': {
'type': 'azure',
'connectionStringName': 'AzureWebJobsStorage',
'controlQueueBatchSize': 32,
'maxQueuePollingInterval': '00:00:02'
}
}
}
}Tratamento de erros e novas tentativas
As funções de atividade podem lançar exceções, que são propagadas de volta para a função orquestradora como TaskFailedException. Use blocos try-catch na função orquestradora para tratar falhas de forma adequada. Para erros transitórios, configure novas tentativas automáticas com espera progressiva usando callActivityWithRetry, especificando o número máximo de tentativas, o primeiro intervalo de nova tentativa e o coeficiente de espera progressiva. Este é o padrão recomendado para atividades que chamam APIs ou bancos de dados externos.
// Orchestrator: retry an activity with exponential backoff
module.exports = df.orchestrator(function* (context) {
const retryOptions = new df.RetryOptions(
5000, // firstRetryIntervalInMilliseconds
3 // maxNumberOfAttempts
);
retryOptions.backoffCoefficient = 2; // 5s, 10s, 20s
try {
const result = yield context.df.callActivityWithRetry(
'CallExternalAPI',
retryOptions,
context.df.getInput()
);
return result;
} catch (e) {
yield context.df.callActivity('SendFailureAlert', e.message);
throw e;
}
});Entidades Durable
As entidades Durable (funções de entidade) implementam pequenas partes de estado durável acessíveis por identidade — de modo semelhante a atores virtuais. Uma entidade tem um ID e um estado que persiste entre chamadas. Você chama operações em uma entidade a partir de uma função orquestradora ou de um cliente, e a entidade as processa uma por vez (em série). Os usos comuns incluem contadores, máquinas de estado de aprovação, limitadores de taxa e carrinhos de compras — qualquer cenário que exija um estado durável e atualizável sem um banco de dados.
// Counter entity function
const df = require('durable-functions');
module.exports = df.entity(function (context) {
let count = context.df.getState(() => 0);
const operation = context.df.operationName;
if (operation === 'add') count += context.df.getInput();
if (operation === 'reset') count = 0;
if (operation === 'get') context.df.return(count);
context.df.setState(count);
});
// From orchestrator, increment counter entity
// const entityId = new df.EntityId('Counter', 'myCounter');
// yield context.df.callEntity(entityId, 'add', 1);Verificação rápida
Teste sua compreensão dos conceitos do Microsoft Azure Fundamentos (AZ-900) apresentados nesta lição.
Recapitulação da lição
Nesta lição, você aprendeu que as funções Durable permitem fluxos de trabalho com estado e de longa duração ao criarem pontos de verificação do estado da função orquestradora no Azure Storage; os principais padrões incluem encadeamento, fan-out/fan-in, monitoramento e interação humana; e as funções orquestradoras devem ser determinísticas — toda E/S e todas as chamadas não determinísticas devem passar por funções de atividade. A seguir, exploraremos o Azure Logic Apps.
Perguntas Frequentes
A aula “Durable Functions para Fluxos de Trabalho com Estado” é grátis?
Sim — o texto completo de “Durable Functions para Fluxos de Trabalho com Estado” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Cloud & IT Cert Prep, atualize para CoddyKit PRO. O curso de Cloud & IT Cert Prep inclui 4 aulas no total.
O que vou aprender em “Durable Functions para Fluxos de Trabalho com Estado”?
Orquestre fluxos de trabalho de longa duração usando padrões de orquestração do Durable Functions (distribuição e agregação, encadeamento, monitoramento) e compreenda como o estado é salvo em pontos… Você pratica Cloud & IT Cert Prep com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Cloud & IT Cert Prep?
Nenhuma experiência prévia é necessária. Cloud & IT Cert Prep no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Durable Functions para Fluxos de Trabalho com Estado”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Cloud & IT Cert Prep?
Sim. Cada aula de Cloud & IT Cert Prep inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Gatilhos e Associações do Azure Functions
- Durable Functions para Fluxos de Trabalho com Estado
- Azure Logic Apps
- Event Grid e Arquitetura Orientada a Eventos