Udostępnij za pośrednictwem


Niestandardowy stan orkiestracji w Durable Functions (Azure Functions)

Niestandardowy stan orkiestracji umożliwia ustawienie niestandardowej wartości stanu dla funkcji orkiestratora. Ten stan jest udostępniany za pośrednictwem interfejsu API GetStatus PROTOKOŁU HTTP lub równoważnego interfejsu API zestawu SDK w obiekcie klienta aranżacji.

Przykładowe przypadki użycia

Wizualizowanie postępu

Klienci mogą sondować punkt końcowy stanu i wyświetlać interfejs użytkownika postępu, który wizualizuje bieżący etap wykonywania. W poniższym przykładzie pokazano udostępnianie postępu:

Uwaga

Te przykłady w języku C# są napisane dla Durable Functions 2.x i nie są zgodne z Durable Functions 1.x. Aby uzyskać więcej informacji na temat różnic między wersjami, zobacz artykuł Durable Functions versions (Wersje Durable Functions).

[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}!";
}

Następnie klient otrzyma dane wyjściowe orkiestracji tylko wtedy, gdy CustomStatus pole jest ustawione na "Londyn":

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

Dostosowywanie danych wyjściowych

Innym interesującym scenariuszem jest segmentowanie użytkowników przez zwracanie dostosowanych danych wyjściowych na podstawie unikatowych cech lub interakcji. Dzięki użyciu niestandardowego stanu orkiestracji kod po stronie klienta pozostanie ogólny. Wszystkie główne modyfikacje zostaną wprowadzone po stronie serwera, jak pokazano w poniższym przykładzie:

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

Specyfikacja instrukcji

Orkiestrator może dostarczyć klientom unikatowe instrukcje za pośrednictwem stanu niestandardowego. Instrukcje dotyczące stanu niestandardowego zostaną zamapowane na kroki w kodzie orkiestracji:

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

Wykonywanie zapytań dotyczących stanu niestandardowego za pomocą protokołu HTTP

W poniższym przykładzie pokazano, jak można wykonywać zapytania dotyczące niestandardowych wartości stanu przy użyciu wbudowanych interfejsów API PROTOKOŁU HTTP.

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

Gdy orkiestracja jest uruchomiona, klienci zewnętrzni mogą pobrać ten stan niestandardowy:

GET /runtime/webhooks/durabletask/instances/instance123

Klienci otrzymają następującą odpowiedź:

{
  "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"
}

Ostrzeżenie

Niestandardowy ładunek stanu jest ograniczony do 16 KB tekstu JSON UTF-16. Zalecamy użycie magazynu zewnętrznego, jeśli potrzebujesz większego ładunku.

Następne kroki