Nastavení a dotazování vlastního stavu orchestrace

Stav vlastní orchestrace umožňuje připojit libovolná metadata ve formátu JSON k běžící instanci orchestrace, takže externí klienti ji mohou kdykoli dotazovat. Vlastní stav použijte v případě, že potřebujete:

  • Hlásit průběh v polovině letu – nechte uživatelské rozhraní ukázat, ke kterému kroku orchestrace došlo, aniž by čekalo na dokončení.
  • Vraťte dynamická data volajícím – doporučení, informace o slevě nebo pokyny pro další kroky, zatímco orchestrace stále probíhá.
  • Koordinujte se s externími systémy – sdílejte stav, na který se ostatní služby nebo lidské operátory mohou dotazovat a podle něj jednat.

Výstraha

Datový objem vlastního stavu je omezen na 16 kilobajtů textu JSON ve formátu UTF-16. Pokud potřebujete větší objem dat, použijte externí úložiště a uložte odkaz (například adresu URL objektu blob) do uživatelského stavu.

V Azure Functions je tento stav k dispozici prostřednictvím rozhraní HTTP GetStatus API nebo ekvivalentního rozhraní API SDK v objektu klienta orchestrace.

V sadách SDK trvalých úloh je tento stav dostupný prostřednictvím rozhraní API pro dotazy na stav orchestrace na DurableTaskClient (například GetInstanceAsync v .NET nebo getInstanceMetadata v Java).

Důležité

V současné době není sada POWERShell Durable Task SDK dostupná.

Ukázkové případy použití pro vlastní stav orchestrace

Následující tabulka shrnuje běžné vzory. Pokud chcete přejít na odpovídající příklad, vyberte případ použití.

Případ použití Description
Vizualizace průběhu orchestrace Po každé aktivitě aktualizujte řetězec nebo objekt, aby klienti mohli zobrazit indikátor průběhu.
Vrácení dynamických metadat klientům Nastavte strukturovaná data (například doporučení), která klienti vykreslují, aniž by potřebovali vlastní koncové body na straně serveru.
Poskytnutí dat umožňujících akci klientům Zveřejněte adresy URL rezervací, informace o slevě nebo pokyny k dalším krokům, na které klienti budou reagovat, zatímco orchestrace čeká na externí událost.
Dotazování na vlastní status Přečtěte si vlastní hodnotu stavu z klienta pomocí rozhraní HTTP API nebo volání sady SDK.

Vizualizace průběhu orchestrace

V tomto vzoru orchestrátor volá SetCustomStatus (nebo ekvivalent v příslušném jazyce) po dokončení každé aktivity a aktualizuje stav názvem naposledy dokončeného města. Klient se dotazuje na koncový bod stavu, přečte aktuální hodnotu a aktualizuje indikátor průběhu v uživatelském rozhraní.

Následující ukázka ukazuje sdílení průběhu pomocí koncového bodu stavu protokolu HTTP Durable Functions:

Poznámka:

Tyto příklady jsou napsané pro Durable Functions 2.x a nejsou kompatibilní s Durable Functions 1.x. Další informace o rozdílech mezi verzemi najdete v článku o verzích 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}!";
}

Následující ukázka ukazuje sdílení průběhu pomocí klientských rozhraní API sady Durable Task SDK:

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

Klient může dotazovat metadata orchestrace a čekat, až bude pole nastaveno CustomStatus na "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;
}

Následující kód klienta kontroluje stav orchestrace a čeká, dokud není CustomStatus nastaven na "London", před vrácením odpovědi:

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

Vrácení dynamických metadat klientům

Pomocí vlastního stavu orchestrace můžete klientům vrátit strukturovaná data , jako jsou přizpůsobená doporučení, aniž byste museli vytvářet samostatné koncové body. Orchestrátor nastaví vlastní stav na základě vstupu a klient ho přečte přes standardní stavové rozhraní API. Tím zůstane obecný kód na straně klienta, zatímco veškerá logika zůstane na straně serveru.

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

Poskytnutí dat umožňujících akci klientům

V tomto vzoru orchestrátor zobrazí časově citlivé informace, jako je sleva, adresa URL rezervace a časový limit, prostřednictvím vlastního stavu a poté se pozastaví, aby čekal na externí událost. Klient přečte uživatelský stav, aby zobrazil nabídku, a po akci uživatele odešle potvrzovací událost zpět orchestrátoru.

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

Dotaz na vlastní stav orchestrace

Předchozí příklady ukazují, jak nastavit vlastní stav z kódu orchestrátoru. Tato část se zaměřuje na to, jak externí klienti tuto hodnotu čtou.

Jakmile orchestrátor zavolá SetCustomStatus, můžou se externí klienti dotazovat na hodnotu prostřednictvím integrovaného Durable Functions rozhraní HTTP API. Například:

GET /runtime/webhooks/durabletask/instances/instance123

Odpověď obsahuje customStatus pole spolu s metadaty modulu runtime:

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

Vlastní stav můžete také programově dotazovat pomocí orchestračního klienta SDK. Kompletní referenční informace najdete v tématu Instance dotazů.

Sady SDK trvalých úloh neposkytují integrovaný koncový bod stavu HTTP. Místo toho můžete prostřednictvím kódu programu dotazovat vlastní stav pomocí rozhraní API metadat instance orchestrace v objektu DurableTaskClient.

using Microsoft.DurableTask.Client;

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

Výstraha

Datový objem vlastního stavu je omezen na 16 kilobajtů textu JSON ve formátu UTF-16.

Další kroky