Festlegen und Abfragen des benutzerdefinierten Orchestrierungsstatus

Mit dem benutzerdefinierten Orchestrierungsstatus können Sie beliebige JSON-Metadaten an eine ausgeführte Orchestrierungsinstanz anfügen, damit externe Clients sie jederzeit abfragen können. Verwenden Sie den benutzerdefinierten Status, wenn Sie Folgendes benötigen:

  • Fortschritt während des Fluges melden – Lassen Sie eine Benutzeroberfläche anzeigen, welchen Schritt eine Orchestrierung erreicht hat, ohne darauf zu warten, dass sie abgeschlossen ist.
  • Zurückgeben dynamischer Daten an Aufrufer: Zeigen Sie Empfehlungen, Rabattinformationen oder Anleitungen für die nächsten Schritte an, während die Orchestrierung noch ausgeführt wird.
  • Koordinieren Sie mit externen Systemen – teilen Sie den Status so mit, dass andere Dienste oder menschliche Betreiber ihn abfragen und darauf reagieren können.

Warnung

Die benutzerdefinierte Statusnutzlast ist auf 16 KB UTF-16 JSON-Text beschränkt. Wenn Sie eine größere Nutzlast benötigen, verwenden Sie stattdessen externen Speicher, und speichern Sie einen Verweis (z. B. eine BLOB-URL) im benutzerdefinierten Status.

In Azure Functions ist dieser Status über die HTTP GetStatus-API oder die entsprechende SDK-API für das Orchestrierungsclientobjekt verfügbar.

In dauerhaften Task-SDKs ist dieser Status über die API zur Abfrage des Orchestrierungsstatus im DurableTaskClient verfügbar (z. B. GetInstanceAsync in .NET oder getInstanceMetadata in Java).

Von Bedeutung

Derzeit ist das PowerShell Durable Task SDK nicht verfügbar.

Beispielanwendungsfälle für den benutzerdefinierten Orchestrierungsstatus

In der folgenden Tabelle sind allgemeine Muster zusammengefasst. Wählen Sie einen Anwendungsfall aus, um zum entsprechenden Beispiel zu springen.

Anwendungsfall BESCHREIBUNG
Visualisieren des Orchestrierungsfortschritts Aktualisieren Sie nach jeder Aktivität eine Zeichenfolge oder ein Objekt, damit Clients eine Statusanzeige anzeigen können.
Zurückgeben dynamischer Metadaten an Clients Legen Sie strukturierte Daten (z. B. Empfehlungen) fest, die Clients rendern, ohne benutzerdefinierte serverseitige Endpunkte zu benötigen.
Bereitstellung von umsetzbaren Daten für Kunden Präsentieren Sie Buchungs-URLs, Rabattinformationen oder Anweisungen für den nächsten Schritt, auf die Kunden reagieren können, während die Orchestrierung auf ein externes Ereignis wartet.
Benutzerdefinierter Status abfragen Lesen Sie den benutzerdefinierten Statuswert von einem Client mithilfe von HTTP-APIs oder SDK-Aufrufen.

Visualisieren des Orchestrierungsfortschritts

In diesem Muster ruft der Orchestrator nach Abschluss jeder Aktivität SetCustomStatus (oder die entsprechende Funktion in Ihrer Sprache) auf und aktualisiert den Status mit dem Namen der zuletzt abgeschlossenen Stadt. Ein Client fragt den Statusendpunkt ab, liest den aktuellen Wert und aktualisiert eine Statusanzeige auf der Benutzeroberfläche.

Im folgenden Beispiel wird die Fortschrittsverfolgung zur Statusfreigabe mithilfe des Durable Functions-HTTP-Statusendpunkts veranschaulicht.

Hinweis

Diese Beispiele werden für Durable Functions 2.x geschrieben und sind nicht mit Durable Functions 1.x kompatibel. Weitere Informationen zu den Unterschieden zwischen den Versionen finden Sie im Artikel Durable Functions-Versionen.

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

Im folgenden Beispiel wird die Fortschrittsübermittlung mithilfe der Client-APIs des Durable Task SDK demonstriert.

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

Der Client kann Orchestrierungsmetadaten abfragen und warten, bis das CustomStatus Feld auf folgendes "London"festgelegt ist:

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

Der folgende Clientcode fragt den Orchestrierungsstatus ab und wartet, bis CustomStatus auf "London" festgelegt ist, bevor eine Antwort zurückgegeben wird.

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

Zurückgeben dynamischer Metadaten an Clients

Sie können den benutzerdefinierten Orchestrierungsstatus verwenden, um strukturierte Daten , z. B. personalisierte Empfehlungen, an Clients zurückzugeben, ohne separate Endpunkte zu erstellen. Der Orchestrator legt den benutzerdefinierten Status basierend auf der Eingabe fest, und der Client liest ihn über die Standardstatus-API. Dadurch bleiben clientseitiger Code generisch, während alle Logik auf der Serverseite bleibt.

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

Bereitstellen von umsetzbaren Daten für Clients

In diesem Muster zeigt der Orchestrator zeitabhängige Informationen an – z. B. einen Rabatt, eine Buchungs-URL und ein Timeout – über den benutzerdefinierten Status und pausiert dann, um auf ein externes Ereignis zu warten. Ein Client liest den benutzerdefinierten Status, um das Angebot anzuzeigen, und sendet das Bestätigungsereignis zurück an den Orchestrator, wenn der Benutzer agiert.

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

Individueller Orchestrierungsstatus abfragen

In den vorherigen Beispielen wird gezeigt, wie Sie den benutzerdefinierten Status aus Orchestratorcode festlegen. In diesem Abschnitt wird erläutert, wie externe Clients diesen Wert lesen.

Nachdem ein Orchestrator SetCustomStatus aufgerufen hat, können externe Clients den Wert über die integrierte Durable Functions HTTP-API abfragen. Beispiel:

GET /runtime/webhooks/durabletask/instances/instance123

Die Antwort enthält das customStatus Feld zusammen mit Laufzeitmetadaten:

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

Sie können auch den benutzerdefinierten Status programmgesteuert mithilfe des Orchestrierungsclient-SDK abfragen. Eine vollständige Referenz finden Sie unter Abfrageinstanzen.

Dauerhafte Aufgaben-SDKs stellen keinen integrierten HTTP-Statusendpunkt bereit. Fragen Sie stattdessen den benutzerdefinierten Status programmgesteuert mithilfe der Orchestrierungsinstanz-Metadaten-APIs auf der DurableTaskClient ab.

using Microsoft.DurableTask.Client;

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

Warnung

Die benutzerdefinierte Statusnutzlast ist auf 16 KB UTF-16 JSON-Text beschränkt.

Nächste Schritte