在 Durable Functions 中处理外部事件 (Azure Functions)Handling external events in Durable Functions (Azure Functions)

业务流程协调程序函数能够等待和侦听外部事件。Orchestrator functions have the ability to wait and listen for external events. Durable Functions 的此功能对于处理人机交互或其他外部触发器通常比较有用。This feature of Durable Functions is often useful for handling human interaction or other external triggers.

备注

外部事件是单向的异步操作。External events are one-way asynchronous operations. 它们不适用于发送事件的客户端需要来自业务流程协调程序函数的同步响应的情况。They are not suitable for situations where the client sending the event needs a synchronous response from the orchestrator function.

等待事件Wait for events

借助业务流程触发器绑定WaitForExternalEvent (.NET) 和 waitForExternalEvent (JavaScript) 方法,业务流程协调程序函数可异步等待和侦听外部事件。The WaitForExternalEvent (.NET) and waitForExternalEvent (JavaScript) methods of the orchestration trigger binding allow an orchestrator function to asynchronously wait and listen for an external event. 侦听业务流程协调程序函数声明了事件的“名称”和它期望收到的“数据形态”。 The listening orchestrator function declares the name of the event and the shape of the data it expects to receive.

[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
    }
}

备注

前面的 C# 代码适用于 Durable Functions 2.x。The previous C# code is for Durable Functions 2.x. 对于 Durable Functions 1.x,必须使用 DurableOrchestrationContext 而不是 IDurableOrchestrationContextFor Durable Functions 1.x, you must use DurableOrchestrationContext instead of IDurableOrchestrationContext. 有关版本之间差异的详细信息,请参阅 Durable Functions 版本一文。For more information about the differences between versions, see the Durable Functions versions article.

前面的示例侦听特定单个事件,并在收到该事件时执行操作。The preceding example listens for a specific single event and takes action when it's received.

可以同时侦听多个事件,像以下示例中一样,以下示例等待三个可能的事件通知之一。You can listen for multiple events concurrently, like in the following example, which waits for one of three possible event notifications.

[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)
    {
        // ...
    }
}

备注

前面的 C# 代码适用于 Durable Functions 2.x。The previous C# code is for Durable Functions 2.x. 对于 Durable Functions 1.x,必须使用 DurableOrchestrationContext 而不是 IDurableOrchestrationContextFor Durable Functions 1.x, you must use DurableOrchestrationContext instead of IDurableOrchestrationContext. 有关版本之间差异的详细信息,请参阅 Durable Functions 版本一文。For more information about the differences between versions, see the Durable Functions versions article.

前面的示例侦听多个事件中的“任何一个”。 The previous example listens for any of multiple events. 还可以等待“所有”事件。 It's also possible to wait for all events.

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

备注

前面的代码适用于 Durable Functions 2.x。The previous code is for Durable Functions 2.x. 对于 Durable Functions 1.x,必须使用 DurableOrchestrationContext 而不是 IDurableOrchestrationContextFor Durable Functions 1.x, you must use DurableOrchestrationContext instead of IDurableOrchestrationContext. 有关版本之间差异的详细信息,请参阅 Durable Functions 版本一文。For more information about the differences between versions, see the Durable Functions versions article.

在 .NET 中,如果事件负载无法转换为预期类型 T,将会引发异常。In .NET, if the event payload cannot be converted into the expected type T, an exception is thrown.

WaitForExternalEvent 无限期地等待一些输入。WaitForExternalEvent waits indefinitely for some input. 在等待时,可以安全地卸载函数应用。The function app can be safely unloaded while waiting. 对于此业务流程实例,如果某个事件到达,则会自动唤醒并立即处理该事件。If and when an event arrives for this orchestration instance, it is awakened automatically and immediately processes the event.

备注

如果函数应用使用消耗计划,当业务流程协调程序函数等待来自 WaitForExternalEvent (.NET) 或 waitForExternalEvent (JavaScript) 的任务时,无论它等待多久,都不会产生账单费用。If your function app uses the Consumption Plan, no billing charges are incurred while an orchestrator function is awaiting a task from WaitForExternalEvent (.NET) or waitForExternalEvent (JavaScript), no matter how long it waits.

发送事件Send events

可以使用 RaiseEventAsync (.NET) 或 raiseEventAsync (JavaScript) 方法将外部事件发送到业务流程。You can use the RaiseEventAsync (.NET) or raiseEventAsync (JavaScript) methods to send an external event to an orchestration. 这些方法由业务流程客户端绑定公开。These methods are exposed by the orchestration client binding. 还可以使用内置引发事件 HTTP API 将外部事件发送到业务流程。You can also use the built-in raise event HTTP API to send an external event to an orchestration.

引发的事件包括实例 ID、eventName 和 eventData 等参数。A raised event includes an instance ID, an eventName, and eventData as parameters. 业务流程协调程序函数使用 WaitForExternalEvent (.NET) 或 waitForExternalEvent (JavaScript) API 处理这些事件。Orchestrator functions handle these events using the WaitForExternalEvent (.NET) or waitForExternalEvent (JavaScript) APIs. 在发送端和接收端,eventName 必须匹配才能处理事件。The eventName must match on both the sending and receiving ends in order for the event to be processed. 事件数据还必须是 JSON 可序列化的。The event data must also be JSON-serializable.

在内部,“引发事件”机制将正在等待的业务流程协调程序函数选取的消息排入队列。Internally, the "raise event" mechanisms enqueue a message that gets picked up by the waiting orchestrator function. 如果实例没有在等待指定的事件名,则将事件消息添加到内存中队列**。If the instance is not waiting on the specified event name, the event message is added to an in-memory queue. 如果业务流程实例稍后开始侦听该事件名称,** 它将检查队列中的事件消息。If the orchestration instance later begins listening for that event name, it will check the queue for event messages.

备注

如果没有具有指定实例 ID 的业务流程实例,则丢弃事件消息。If there is no orchestration instance with the specified instance ID, the event message is discarded.

下面是一个示例队列触发的函数,它将“Approval”事件发送到一个业务流程协调程序函数实例。Below is an example queue-triggered function that sends an "Approval" event to an orchestrator function instance. 业务流程实例 ID 来自队列消息的正文。The orchestration instance ID comes from the body of the queue message.

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

备注

前面的 C# 代码适用于 Durable Functions 2.x。The previous C# code is for Durable Functions 2.x. 对于 Durable Functions 1.x,必须使用 OrchestrationClient 属性而不是 DurableClient 属性,并且必须使用 DurableOrchestrationClient 参数类型而不是 IDurableOrchestrationClientFor Durable Functions 1.x, you must use OrchestrationClient attribute instead of the DurableClient attribute, and you must use the DurableOrchestrationClient parameter type instead of IDurableOrchestrationClient. 有关版本之间差异的详细信息,请参阅 Durable Functions 版本一文。For more information about the differences between versions, see the Durable Functions versions article.

在内部,RaiseEventAsync (.NET) 或 raiseEvent (JavaScript) 将正在等待的业务流程协调程序函数选取的消息排入队列。Internally, RaiseEventAsync (.NET) or raiseEvent (JavaScript) enqueues a message that gets picked up by the waiting orchestrator function. 如果实例没有在等待指定的事件名,则将事件消息添加到内存中队列**。If the instance is not waiting on the specified event name, the event message is added to an in-memory queue. 如果业务流程实例稍后开始侦听该事件名称,** 它将检查队列中的事件消息。If the orchestration instance later begins listening for that event name, it will check the queue for event messages.

备注

如果没有具有指定实例 ID 的业务流程实例,则丢弃事件消息。If there is no orchestration instance with the specified instance ID, the event message is discarded.

HTTPHTTP

以下是向业务流程实例引发“批准”事件的 HTTP 请求的示例。The following is an example of an HTTP request that raises an "Approval" event to an orchestration instance.

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

"true"

在本例中,实例 ID 硬编码为 MyInstanceId。In this case, the instance ID is hardcoded as MyInstanceId.

后续步骤Next steps