Durable Functions para flujos de trabajo con estado
Orqueste flujos de trabajo de larga duración mediante patrones de orquestador de Durable Functions (fan-out/fan-in, encadenamiento y monitorización) y comprenda cómo se guardan los puntos de control del estado.
Durable Functions para flujos de trabajo con estado es una lección gratuita de Cloud & IT Cert Prep en CoddyKit. Esta es la lección 2 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Cloud & IT Cert Prep, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Cloud & IT Cert Prep incluye 4 lecciones en total.
¿Por qué Durable Functions?
Las Azure Functions normales no tienen estado: cada invocación se ejecuta de forma independiente, sin memoria de las llamadas anteriores. Durable Functions amplía Azure Functions con la capacidad de escribir flujos de trabajo con estado y de larga duración mediante código async/await convencional. Durable Task Framework crea automáticamente puntos de control del estado en Azure Storage después de cada paso, por lo que los flujos de trabajo pueden sobrevivir a reinicios del servidor, tiempos de espera o mantenimientos planificados y reanudarse exactamente donde se interrumpieron.
Los tres tipos de funciones
Durable Functions introduce tres tipos de funciones. Una función de orquestador coordina el flujo de trabajo general: llama a funciones de actividad y espera los resultados mediante yield o await sin bloquear realmente un subproceso. Una función de actividad realiza una unidad de trabajo concreta (llamar a una API, escribir en una base de datos) y es el único lugar donde deben producirse efectos secundarios. Una función de entidad mantiene pequeñas partes de estado durable (contadores, indicadores) entre llamadas.
// 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);
};Patrón de encadenamiento
El patrón de encadenamiento ejecuta funciones de actividad secuencialmente y pasa la salida de una como entrada de la siguiente. El orquestador espera cada actividad por turnos. Si alguna actividad falla, el flujo de trabajo se detiene y puede reiniciarse desde el paso que produjo el error. Este es el patrón más sencillo de Durable Functions y resulta adecuado para flujos de trabajo en los que cada paso depende del resultado del anterior, como las canalizaciones de procesamiento 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 };
});Patrón de distribución y agregación
El patrón de distribución y agregación inicia varias funciones de actividad en paralelo y espera a que todas finalicen antes de continuar. El orquestador inicia todas las tareas simultáneamente mediante callActivity, sin esperarlas, recopila los objetos de tarea en una matriz y, a continuación, espera con Task.all(). Esto es mucho más rápido que el procesamiento secuencial para elementos de trabajo independientes, como procesar varios archivos, llamar a varias API o realizar operaciones por lotes.
// 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;
});Patrón de supervisión
El patrón de supervisión consulta un sistema externo a intervalos hasta que se cumple una condición, de forma similar a un bucle de consulta, pero completamente durable. El orquestador llama a una actividad para comprobar el estado, espera un intervalo configurable mediante createTimer y, después, repite el proceso. Como el estado se guarda en el almacenamiento entre cada consulta, el orquestador no consume recursos de proceso mientras espera, lo que lo hace mucho más eficiente que un enfoque basado en un temporizador en 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');
});Patrón de interacción humana
El patrón de interacción humana pausa una orquestación y espera un evento externo, como la aprobación de un responsable. El orquestador espera mediante waitForExternalEvent, que puede permanecer días o semanas sin consumir recursos de proceso. Un sistema externo (un enlace de aprobación por correo electrónico, una aplicación móvil o un webhook) llama a la API HTTP de Durable Functions para generar el evento y desbloquear la orquestación. Combínelo con un temporizador para establecer un tiempo de espera automático y realizar una escalación si no llega ninguna respuesta.
// 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';
}
});Restricciones de los orquestadores
Las funciones de orquestador tienen restricciones importantes porque pueden reproducirse varias veces a partir del historial para reconstruir el estado. Deben ser deterministas: nunca use Date.now() ni Math.random(), ni realice llamadas de E/S directas. En su lugar, use context.df.currentUtcDateTime para las marcas de tiempo y llame a funciones de actividad para todas las operaciones de E/S. El registro dentro del cuerpo del orquestador producirá entradas duplicadas durante la reproducción; use funciones de actividad para registrar información.
// 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
});Administración de instancias: estado y terminación
Cada ejecución de una orquestación tiene un identificador de instancia único que puede utilizar para consultar su estado, enviar eventos o terminarla. La API HTTP de administración de Durable Functions proporciona puntos de conexión para comprobar el estado (GET /instances/{id}), enviar eventos (POST /instances/{id}/raiseEvent/{name}) y terminar la instancia (POST /instances/{id}/terminate). Use el enlace de cliente de Durable en sus funciones para acceder a estas operaciones mediante programación.
// 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
}
};
};Backend de almacenamiento y rendimiento
Durable Functions almacena el historial de las orquestaciones, el estado de las instancias y las colas de mensajes entre funciones en una cuenta de Azure Storage (o en backends de Azure SQL/Netherite para obtener un mayor rendimiento). Cada punto de control escribe en Azure Table Storage y Azure Queue Storage. En escenarios de alto rendimiento (miles de orquestaciones simultáneas), el backend de almacenamiento Netherite utiliza Azure Event Hubs para ofrecer un rendimiento mucho mayor. Supervise la profundidad de la cola de orquestaciones para detectar cuellos de botella.
// 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'
}
}
}
}Gestión de errores y reintentos
Las funciones de actividad pueden producir excepciones, que se propagan al orquestador como TaskFailedException. Use bloques try-catch en el orquestador para gestionar los errores correctamente. Para errores transitorios, configure reintentos automáticos con retroceso mediante callActivityWithRetry, especificando el número máximo de intentos, el intervalo del primer reintento y el coeficiente de retroceso. Este es el patrón recomendado para actividades que llaman a API o bases de datos externas.
// 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 durables
Durable Entities (funciones de entidad) implementan pequeñas partes de estado durable accesibles mediante una identidad, de forma similar a los actores virtuales. Una entidad tiene un identificador y un estado que persiste entre llamadas. Puede llamar a operaciones de una entidad desde un orquestador o un cliente, y la entidad las procesa una a una (de forma serializada). Entre los usos habituales se incluyen contadores, máquinas de estados de aprobación, limitadores de velocidad y carritos de compra: cualquier escenario que necesite un estado durable y actualizable sin una base de datos.
// 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);Comprobación rápida
Compruebe su comprensión de los conceptos de Microsoft Azure Fundamentals (AZ-900) de esta lección.
Resumen de la lección
En esta lección ha aprendido que Durable Functions permite crear flujos de trabajo con estado y de larga duración mediante puntos de control del estado del orquestador en Azure Storage; los patrones principales incluyen encadenamiento, distribución y agregación, supervisión e interacción humana; y los orquestadores deben ser deterministas: todas las operaciones de E/S y las llamadas no deterministas deben realizarse mediante funciones de actividad. A continuación, exploraremos Azure Logic Apps.
Preguntas frecuentes
¿La lección «Durable Functions para flujos de trabajo con estado» es gratis?
Sí — el texto completo de «Durable Functions para flujos de trabajo con estado» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Cloud & IT Cert Prep, actualiza a CoddyKit PRO. El curso de Cloud & IT Cert Prep incluye 4 lecciones en total.
¿Qué aprenderé en «Durable Functions para flujos de trabajo con estado»?
Orqueste flujos de trabajo de larga duración mediante patrones de orquestador de Durable Functions (fan-out/fan-in, encadenamiento y monitorización) y comprenda cómo se guardan los puntos de control… Practicas Cloud & IT Cert Prep con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Cloud & IT Cert Prep?
No se requiere experiencia previa. Cloud & IT Cert Prep en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 2 de 4.
¿Cuánto tiempo toma la lección «Durable Functions para flujos de trabajo con estado»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Cloud & IT Cert Prep?
Sí. Cada lección de Cloud & IT Cert Prep incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Desencadenadores y enlaces de Azure Functions
- Durable Functions para flujos de trabajo con estado
- Azure Logic Apps
- Event Grid y arquitectura controlada por eventos