Durable Functions 中的自定义业务流程状态 (Azure Functions)Custom orchestration status in Durable Functions (Azure Functions)

使用自定义业务流程状态,可以为业务流程协调程序函数设置自定义状态值。Custom orchestration status lets you set a custom status value for your orchestrator function. 此状态通过业务流程客户端上的 HTTP GetStatus APIGetStatusAsyncAPI 提供。This status is provided via the HTTP GetStatus API or the GetStatusAsync API on the orchestration client.

示例用例Sample use cases

备注

以下示例演示如何在 C# 和 JavaScript 中使用自定义状态功能。The following samples show how to use custom status feature in C# and JavaScript. C# 示例是针对 Durable Functions 2.x 编写的,与 Durable Functions 1.x 不兼容。The C# examples are written for Durable Functions 2.x and are not compatible with Durable Functions 1.x. 有关版本之间差异的详细信息,请参阅 Durable Functions 版本一文。For more information about the differences between versions, see the Durable Functions versions article.

显示进度Visualize progress

客户端可以轮询状态终结点,并显示进度 UI 来直观显示当前执行阶段。Clients can poll the status end point and display a progress UI that visualizes the current execution stage. 以下示例演示了进度共享:The following sample demonstrates progress sharing:

[FunctionName("E1_HelloSequence")]
public static async Task<List<string>> Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var outputs = new List<string>();

    outputs.Add(await context.CallActivityAsync<string>("E1_SayHello", "Tokyo"));
    context.SetCustomStatus("Tokyo");
    outputs.Add(await context.CallActivityAsync<string>("E1_SayHello", "Seattle"));
    context.SetCustomStatus("Seattle");
    outputs.Add(await context.CallActivityAsync<string>("E1_SayHello", "London"));
    context.SetCustomStatus("London");

    // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
    return outputs;
}

[FunctionName("E1_SayHello")]
public static string SayHello([ActivityTrigger] string name)
{
    return $"Hello {name}!";
}

然后,只有当 CustomStatus 字段设置为“London”时,客户端才会收到业务流程的输出:And then the client will receive the output of the orchestration only when CustomStatus field is set to "London":

[FunctionName("HttpStart")]
public static async Task<HttpResponseMessage> Run(
    [HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}")] HttpRequestMessage req,
    [DurableClient] IDurableOrchestrationClient starter,
    string functionName,
    ILogger log)
{
    // Function input comes from the request content.
    dynamic eventData = await req.Content.ReadAsAsync<object>();
    string instanceId = await starter.StartNewAsync(functionName, (string)eventData);

    log.LogInformation($"Started orchestration with ID = '{instanceId}'.");

    DurableOrchestrationStatus durableOrchestrationStatus = await starter.GetStatusAsync(instanceId);
    while (durableOrchestrationStatus.CustomStatus.ToString() != "London")
    {
        await Task.Delay(200);
        durableOrchestrationStatus = await starter.GetStatusAsync(instanceId);
    }

    HttpResponseMessage httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new StringContent(JsonConvert.SerializeObject(durableOrchestrationStatus))
    };

    return httpResponseMessage;
  }
}

输出自定义Output customization

另一个有趣的方案是通过基于独特的特征或交互返回自定义输出对用户进行细分。Another interesting scenario is segmenting users by returning customized output based on unique characteristics or interactions. 借助自定义业务流程状态,客户端代码将保持为泛型。With the help of custom orchestration status, the client-side code will stay generic. 所有主要修改都将发生在服务器端,如以下示例中所示:All main modifications will happen on the server side as shown in the following sample:

[FunctionName("CityRecommender")]
public static void Run(
  [OrchestrationTrigger] IDurableOrchestrationContext context)
{
  int userChoice = context.GetInput<int>();

  switch (userChoice)
  {
    case 1:
    context.SetCustomStatus(new
    {
      recommendedCities = new[] {"Tokyo", "Seattle"},
      recommendedSeasons = new[] {"Spring", "Summer"}
     });
      break;
    case 2:
      context.SetCustomStatus(new
      {
        recommendedCities = new[] {"Seattle, London"},
        recommendedSeasons = new[] {"Summer"}
      });
        break;
      case 3:
      context.SetCustomStatus(new
      {
        recommendedCities = new[] {"Tokyo, London"},
        recommendedSeasons = new[] {"Spring", "Summer"}
      });
        break;
  }

  // Wait for user selection and refine the recommendation
}

指令规范Instruction specification

业务流程协调程序可以通过自定义状态为客户端提供独特指令。The orchestrator can provide unique instructions to the clients via the custom state. 自定义状态指令将映射到业务流程代码中的步骤:The custom status instructions will be mapped to the steps in the orchestration code:

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

  int discount = await context.CallActivityAsync<int>("CalculateDiscount", userId);

  context.SetCustomStatus(new
  {
    discount = discount,
    discountTimeout = 60,
    bookingUrl = "https://www.myawesomebookingweb.com",
  });

  bool isBookingConfirmed = await context.WaitForExternalEvent<bool>("BookingConfirmed");

  context.SetCustomStatus(isBookingConfirmed
    ? new {message = "Thank you for confirming your booking."}
    : new {message = "The booking was not confirmed on time. Please try again."});

  return isBookingConfirmed;
}

示例Sample

在下面的示例中,首先设置了自定义状态;In the following sample, the custom status is set first;

public static async Task SetStatusTest([OrchestrationTrigger] IDurableOrchestrationContext context)
{
    // ...do work...

    // update the status of the orchestration with some arbitrary data
    var customStatus = new { nextActions = new [] {"A", "B", "C"}, foo = 2, };
    context.SetCustomStatus(customStatus);

    // ...do more work...
}

在业务流程正在运行时,外部客户端可以提取此自定义状态:While the orchestration is running, external clients can fetch this custom status:

GET /runtime/webhooks/durabletask/instances/instance123

客户端将收到以下响应:Clients will get the following response:

{
  "runtimeStatus": "Running",
  "input": null,
  "customStatus": { "nextActions": ["A", "B", "C"], "foo": 2 },
  "output": null,
  "createdTime": "2019-10-06T18:30:24Z",
  "lastUpdatedTime": "2019-10-06T19:40:30Z"
}

警告

自定义状态有效负载限制为 16 KB 的 UTF-16 JSON 文本,因为它需要能够容纳在 Azure 表存储列中。The custom status payload is limited to 16 KB of UTF-16 JSON text because it needs to be able to fit in an Azure Table Storage column. 如果需要更大的有效负载,我们建议使用外部存储。We recommend you use external storage if you need a larger payload.

后续步骤Next steps