Ange och fråga efter anpassad orkestreringsstatus

Med anpassad orkestreringsstatus kan du koppla godtyckliga JSON-metadata till en orkestreringsinstans som körs så att externa klienter kan köra frågor mot den när som helst. Använd anpassad status när du behöver:

  • Rapportförlopp mitt under flygning – låt ett användargränssnitt visa vilket steg en orkestrering har nått utan att vänta på att den ska slutföras.
  • Returnera dynamiska data till anropare – visa rekommendationer, rabattinformation eller instruktioner för nästa steg medan orkestreringen fortfarande körs.
  • Samordna med externa system – dela tillstånd som andra tjänster eller mänskliga operatörer kan avsöka och agera på.

Varning

Nyttolasten för anpassad status är begränsad till 16 KB UTF-16 JSON-text. Om du behöver en större nyttolast använder du extern lagring och lagrar en referens (till exempel en blob-URL) i den anpassade statusen i stället.

I Azure Functions är den här statusen tillgänglig via HTTP GetStatus API eller motsvarande SDK API på orkestreringsklientobjektet.

I Durable Task SDK:er är den här statusen tillgänglig via api:er för orkestreringsstatusfrågor på DurableTaskClient (till exempel GetInstanceAsync i .NET eller getInstanceMetadata i Java).

Viktigt!

PowerShell Durable Task SDK är för närvarande inte tillgängligt.

Exempel på användningsfall för anpassad orkestreringsstatus

I följande tabell sammanfattas vanliga mönster. Välj ett användningsfall för att gå vidare till motsvarande exempel.

Användningsfall Beskrivning
Visualisera orkestreringsframstatus Uppdatera en sträng eller ett objekt efter varje aktivitet så att klienter kan visa en förloppsindikator.
Returnera dynamiska metadata till klienter Ange strukturerade data (till exempel rekommendationer) som klienter renderar utan att behöva anpassade slutpunkter på serversidan.
Tillhandahålla åtgärdsbara data till klienter Visa URL:er för bokning, rabattinformation eller instruktioner för nästa steg som klienterna kan agera på medan orkestreringen väntar på en extern händelse.
Fråga efter anpassad status Läs det anpassade statusvärdet från en klient med http-API:er eller SDK-anrop.

Visualisera orkestreringsframstatus

I det här mönstret anropar orkestratorn SetCustomStatus (eller motsvarande på ditt språk) efter att varje aktivitet har slutförts och uppdaterar statusen med namnet på den senast slutförda staden. En klient avsöker statusslutpunkten, läser det aktuella värdet och uppdaterar en förloppsindikator i användargränssnittet.

Följande exempel visar förloppsdelning med hjälp av Durable Functions HTTP-statusslutpunkt:

Anmärkning

De här exemplen är skrivna för Durable Functions 2.x och är inte kompatibla med Durable Functions 1.x. Mer information om skillnaderna mellan versioner finns i artikeln Durable Functions-versioner .

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

Följande exempel visar förloppsdelning med SDK-klient-API:er för Durable Task:

using System.Threading.Tasks;
using Microsoft.DurableTask;

public class HelloCities : TaskOrchestrator<object?, string>
{
    public override async Task<string> RunAsync(TaskOrchestrationContext context, object? input)
    {
        string result = "";

        result += await context.CallActivityAsync<string>("SayHello", "Tokyo") + ", ";
        context.SetCustomStatus("Tokyo");

        result += await context.CallActivityAsync<string>("SayHello", "London") + ", ";
        context.SetCustomStatus("London");

        result += await context.CallActivityAsync<string>("SayHello", "Seattle");
        context.SetCustomStatus("Seattle");

        return result;
    }
}

Klienten kan avsöka orkestreringsmetadata och vänta tills fältet CustomStatus är inställt på "London":

using System.Threading.Tasks;
using Microsoft.DurableTask.Client;

string instanceId = await client.ScheduleNewOrchestrationInstanceAsync("HelloCities");

OrchestrationMetadata metadata = await client.WaitForInstanceStartAsync(instanceId, getInputsAndOutputs: true);
while (metadata.SerializedCustomStatus is null || metadata.ReadCustomStatusAs<string>() != "London")
{
    await Task.Delay(200);
    metadata = await client.GetInstanceAsync(instanceId, getInputsAndOutputs: true) ?? metadata;
}

Följande klientkod avsöker statusen för orkestreringen och väntar tills CustomStatus har angetts till "London" innan ett svar returneras.

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

Returnera dynamiska metadata till klienter

Du kan använda anpassad orkestreringsstatus för att returnera strukturerade data , till exempel anpassade rekommendationer, till klienter utan att skapa separata slutpunkter. Orchestrator anger den anpassade statusen baserat på indata och klienten läser den via standardstatus-API:et. Detta behåller kod på klientsidan generisk medan all logik finns kvar på serversidan.

[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
}
using System.Threading.Tasks;
using Microsoft.DurableTask;

public class CityRecommender : TaskOrchestrator<int, object?>
{
    public override Task<object?> RunAsync(TaskOrchestrationContext context, int userChoice)
    {
        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
        return Task.FromResult<object?>(null);
    }
}

Tillhandahålla åtgärdsbara data till klienter

I det här mönstret visar orkestreraren tidskänslig information – till exempel rabatt, en boknings-URL och en timeout – via anpassad status och pausar sedan för att vänta på en extern händelse. En klient läser den anpassade statusen för att visa erbjudandet och skickar bekräftelsehändelsen tillbaka till orchestrator när användaren agerar.

[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;
}
using System.Threading.Tasks;
using Microsoft.DurableTask;

public class ReserveTicket : TaskOrchestrator<string, bool>
{
    public override async Task<bool> RunAsync(TaskOrchestrationContext context, string userId)
    {
        int discount = await context.CallActivityAsync<int>("CalculateDiscount", userId);

        context.SetCustomStatus(new
        {
            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;
    }
}

Fråga efter anpassad orkestreringsstatus

I föregående exempel visas hur du anger anpassad status från orchestrator-kod. Det här avsnittet fokuserar på hur externa klienter läser det värdet.

När en orchestrator anropar SetCustomStatus kan externa klienter fråga efter värdet via det inbyggda Durable Functions HTTP-API:et. Som exempel:

GET /runtime/webhooks/durabletask/instances/instance123

Svaret innehåller fältet customStatus tillsammans med körningsmetadata:

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

Du kan också anropa anpassad status programmatiskt med hjälp av orkestreringsklientens SDK. En fullständig referens finns i Frågeinstanser.

Durable Task SDK:er tillhandahåller inte någon inbyggd HTTP-statusslutpunkt. Fråga i stället efter en anpassad status programmatiskt med hjälp av API:er för metadata om orkestreringsinstansen på DurableTaskClient.

using Microsoft.DurableTask.Client;

OrchestrationMetadata? metadata = await client.GetInstanceAsync(instanceId, getInputsAndOutputs: true);
string? customStatusJson = metadata?.SerializedCustomStatus;

Varning

Nyttolasten för anpassad status är begränsad till 16 KB UTF-16 JSON-text.

Nästa steg