Compartir vía


Control de eventos externos con Durable Functions (Azure Functions)

Las funciones de orquestador tienen la capacidad de esperar y escuchar eventos externos. Esta característica de Durable Functions suele ser útil para controlar las interacciones humanas u otros desencadenadores externos.

Nota

Los eventos externos son operaciones asincrónicas unidireccionales. No resultan adecuados para situaciones donde el cliente que envía el evento necesita una respuesta sincrónica de la función de orquestador.

Espera de eventos

La API "wait-for-external-event" del enlace del desencadenador de orquestación permite que una función del orquestador espere y escuche de forma asíncrona un evento entregado por un cliente externo. La función de orquestador de escucha declara el nombre del evento y la forma de los datos que espera recibir.

[FunctionName("BudgetApproval")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    bool approved = await context.WaitForExternalEvent<bool>("Approval");
    if (approved)
    {
        // approval granted - do the approved action
    }
    else
    {
        // approval denied - send a notification
    }
}

Nota

El código de C# anterior corresponde a Durable Functions 2.x. En el caso de Durable Functions 1.x, debe usar DurableOrchestrationContext en lugar de IDurableOrchestrationContext. Para obtener más información sobre las diferencias entre versiones, vea el artículo Versiones de Durable Functions.

El ejemplo anterior escucha un evento único específico y toma medidas cuando se recibe.

Puede escuchar varios eventos al mismo tiempo, al igual que en el ejemplo siguiente, que espera una de tres notificaciones de eventos posibles.

[FunctionName("Select")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var event1 = context.WaitForExternalEvent<float>("Event1");
    var event2 = context.WaitForExternalEvent<bool>("Event2");
    var event3 = context.WaitForExternalEvent<int>("Event3");

    var winner = await Task.WhenAny(event1, event2, event3);
    if (winner == event1)
    {
        // ...
    }
    else if (winner == event2)
    {
        // ...
    }
    else if (winner == event3)
    {
        // ...
    }
}

Nota

El código de C# anterior corresponde a Durable Functions 2.x. En el caso de Durable Functions 1.x, debe usar DurableOrchestrationContext en lugar de IDurableOrchestrationContext. Para obtener más información sobre las diferencias entre versiones, vea el artículo Versiones de Durable Functions.

El ejemplo anterior escucha cualquiera de varios eventos posibles. También es posible esperar todos los eventos.

[FunctionName("NewBuildingPermit")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    string applicationId = context.GetInput<string>();

    var gate1 = context.WaitForExternalEvent("CityPlanningApproval");
    var gate2 = context.WaitForExternalEvent("FireDeptApproval");
    var gate3 = context.WaitForExternalEvent("BuildingDeptApproval");

    // all three departments must grant approval before a permit can be issued
    await Task.WhenAll(gate1, gate2, gate3);

    await context.CallActivityAsync("IssueBuildingPermit", applicationId);
}

Nota

El código anterior corresponde a Durable Functions 2.x. En el caso de Durable Functions 1.x, debe usar DurableOrchestrationContext en lugar de IDurableOrchestrationContext. Para obtener más información sobre las diferencias entre versiones, vea el artículo Versiones de Durable Functions.

En .NET, si la carga del evento no se puede convertir al tipo T esperado, se produce una excepción.

La API "wait-for-external-event" espera indefinidamente alguna entrada. La aplicación de función puede descargarse con seguridad mientras espera. En el momento en que un evento llega a esta instancia de orquestación, esta se activa automáticamente y procesa de inmediato el evento.

Nota

Si la aplicación de funciones usa el plan de consumo, no habrá cargos de facturación mientras una función del orquestador esté esperando una tarea de evento externa, sin importar el tiempo que espere.

Al igual que con las Funciones de actividad, los eventos externos tienen una garantía de entrega de al menos una vez. Esto significa que, en determinadas condiciones (como reinicios, escalado, bloqueos, etc.), la aplicación puede recibir duplicados del mismo evento externo. Por lo tanto, se recomienda que los eventos externos contengan algún tipo de identificador que les permita desduplicarse manualmente en orquestadores.

Envío de eventos

Puedes usar la API "raise-event" definida por el enlace del cliente de orquestación para enviar un evento externo a una orquestación. También puede usar la API de HTTP de generación de evento integrada para enviar un evento externo a una orquestación.

Un evento generado incluye valores de instance ID, eventName y eventData como parámetros. Las funciones de Orchestrator controlan estos eventos con las API "wait-for-external-event". El valor de eventName debe coincidir con los extremos de envío y recepción para que se procese el evento. Los datos del evento también se deben poder serializar con JSON.

De manera interna, los mecanismos de "raise-event" ponen en cola un mensaje que recoge la función de orquestador en espera. Si la instancia no está esperando el nombre de evento especificado, el mensaje del evento se agrega a una cola en memoria. Si la instancia de orquestación inicia posteriormente la escucha de ese nombre de evento, se comprobará si hay mensajes de eventos en la cola.

Nota

Si no hay ninguna instancia de orquestación con el identificador de instancia especificado, se descartará el mensaje del evento.

A continuación se muestra una función desencadenada por la cola de ejemplo que envía un evento de aprobación a una instancia de la función de orquestador. El identificador de la instancia de orquestación procede del cuerpo del mensaje de la cola.

[FunctionName("ApprovalQueueProcessor")]
public static async Task Run(
    [QueueTrigger("approval-queue")] string instanceId,
    [DurableClient] IDurableOrchestrationClient client)
{
    await client.RaiseEventAsync(instanceId, "Approval", true);
}

Nota

El código de C# anterior corresponde a Durable Functions 2.x. En el caso de Durable Functions 1.x, debe usar el atributo OrchestrationClient en lugar del atributo DurableClient, además de usar el tipo de parámetro DurableOrchestrationClient en lugar de IDurableOrchestrationClient. Para obtener más información sobre las diferencias entre versiones, vea el artículo Versiones de Durable Functions.

Internamente, la API "raise-event" pone en cola un mensaje que es recogido por la función del orquestador en espera. Si la instancia no espera el nombre de evento especificado, el mensaje de evento se agrega a un búfer en memoria. Si la instancia de orquestación comienza a escuchar ese nombre de evento más tarde, comprobará el búfer en busca de mensajes de evento y activará la tarea que estaba esperando.

Nota

Si no hay ninguna instancia de orquestación con el identificador de instancia especificado, se descartará el mensaje del evento.

HTTP

A continuación, se muestra una solicitud HTTP que genera un evento de "Aprobación" para una instancia de orquestación.

POST /runtime/webhooks/durabletask/instances/MyInstanceId/raiseEvent/Approval&code=XXX
Content-Type: application/json

"true"

En este caso, el id. de la instancia está codificado de forma rígida como MyInstanceId.

Pasos siguientes