カスタム オーケストレーションの状態を使用すると、任意の JSON メタデータを実行中のオーケストレーション インスタンスにアタッチして、外部クライアントがいつでもクエリを実行できるようにします。 次の操作を行う必要がある場合は、カスタム状態を使用します。
-
処理中に進行状況を報告 する — オーケストレーションが完了するのを待たずに、どのステップに達したかを UI に表示します。
- 動的データを呼び出し元に返します。オーケストレーションの実行中に、推奨事項、割引情報、または次の手順を示します。
-
外部システムと連携 する - 他のサービスや人間のオペレーターがポーリングして操作できる状態を共有します。
Warnung
カスタム 状態ペイロードは、UTF-16 JSON テキストの 16 KB に制限されています。 より大きなペイロードが必要な場合は、外部ストレージを使用し、代わりに参照 (BLOB URL など) をカスタム状態に格納します。
Durable Task SDK では、この状態は、DurableTaskClient のオーケストレーション状態クエリ API (たとえば、.NET の GetInstanceAsync、Java の getInstanceMetadata) で使用できます。
Important
現在、PowerShell Durable Task SDK は使用できません。
カスタムオーケストレーション状態の活用事例のサンプル
次の表は、一般的なパターンをまとめたものです。 ユース ケースを選択して、対応する例にジャンプします。
オーケストレーションの進行状況を視覚化する
このパターンでは、オーケストレーターは、各アクティビティが完了した後に SetCustomStatus (または言語で同等のもの) を呼び出し、最後に完了した都市の名前で状態を更新します。 クライアントは、状態エンドポイントをポーリングし、現在の値を読み取り、UI の進行状況インジケーターを更新します。
次の例では、Durable Functions HTTP 状態エンドポイントを使用した進行状況の共有を示します。
注
これらの例は、Durable Functions 2.x 用に記述されており、Durable Functions 1.x と互換性がありません。 バージョン間の相違点の詳細については、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}!";
}
E1_HelloSequence オーケストレーター関数:
const df = require("durable-functions");
module.exports = df.orchestrator(function*(context){
const outputs = [];
outputs.push(yield context.df.callActivity("E1_SayHello", "Tokyo"));
context.df.setCustomStatus("Tokyo");
outputs.push(yield context.df.callActivity("E1_SayHello", "Seattle"));
context.df.setCustomStatus("Seattle");
outputs.push(yield context.df.callActivity("E1_SayHello", "London"));
context.df.setCustomStatus("London");
// returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
return outputs;
});
E1_SayHello アクティビティ関数:
module.exports = async function(context, name) {
return `Hello ${name}!`;
};
E1_HelloSequence オーケストレーター関数
import azure.functions as func
import azure.durable_functions as df
def orchestrator_function(context: df.DurableOrchestrationContext):
output1 = yield context.call_activity('E1_SayHello', 'Tokyo')
context.set_custom_status('Tokyo')
output2 = yield context.call_activity('E1_SayHello', 'Seattle')
context.set_custom_status('Seattle')
output3 = yield context.call_activity('E1_SayHello', 'London')
context.set_custom_status('London')
return [output1, output2, output3]
main = df.Orchestrator.create(orchestrator_function)
E1_SayHello アクティビティ関数
def main(name: str) -> str:
return f"Hello {name}!"
E1_HelloSequence オーケストレーター関数
param($Context)
$output = @()
$output += Invoke-DurableActivity -FunctionName 'E1_SayHello' -Input 'Tokyo'
Set-DurableCustomStatus -CustomStatus 'Tokyo'
$output += Invoke-DurableActivity -FunctionName 'E1_SayHello' -Input 'Seattle'
Set-DurableCustomStatus -CustomStatus 'Seattle'
$output += Invoke-DurableActivity -FunctionName 'E1_SayHello' -Input 'London'
Set-DurableCustomStatus -CustomStatus 'London'
return $output
E1_SayHello アクティビティ関数
param($name)
"Hello $name"
@FunctionName("HelloCities")
public String helloCitiesOrchestrator(
@DurableOrchestrationTrigger(name = "ctx") TaskOrchestrationContext ctx) {
String result = "";
result += ctx.callActivity("SayHello", "Tokyo", String.class).await() + ", ";
ctx.setCustomStatus("Tokyo");
result += ctx.callActivity("SayHello", "London", String.class).await() + ", ";
ctx.setCustomStatus("London");
result += ctx.callActivity("SayHello", "Seattle", String.class).await();
ctx.setCustomStatus("Seattle");
return result;
}
@FunctionName("SayHello")
public String sayHello(@DurableActivityTrigger(name = "name") String name) {
return String.format("Hello %s!", name);
}
次のサンプルは、Durable Task SDK クライアント API を使用した進行状況の共有を示しています。
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;
}
}
from durabletask import task
def say_hello(ctx: task.ActivityContext, name: str) -> str:
return f"Hello {name}!"
def hello_cities(ctx: task.OrchestrationContext, _):
result = ""
result += (yield ctx.call_activity(say_hello, input="Tokyo")) + ", "
ctx.set_custom_status("Tokyo")
result += (yield ctx.call_activity(say_hello, input="London")) + ", "
ctx.set_custom_status("London")
result += yield ctx.call_activity(say_hello, input="Seattle")
ctx.set_custom_status("Seattle")
return result
import com.microsoft.durabletask.TaskOrchestration;
import com.microsoft.durabletask.TaskOrchestrationContext;
public class HelloCities implements TaskOrchestration {
@Override
public void run(TaskOrchestrationContext ctx) {
String result = "";
result += ctx.callActivity("SayHello", "Tokyo", String.class).await() + ", ";
ctx.setCustomStatus("Tokyo");
result += ctx.callActivity("SayHello", "London", String.class).await() + ", ";
ctx.setCustomStatus("London");
result += ctx.callActivity("SayHello", "Seattle", String.class).await();
ctx.setCustomStatus("Seattle");
ctx.complete(result);
}
}
import { ActivityContext, OrchestrationContext, TOrchestrator } from "@microsoft/durabletask-js";
const sayHello = async (_: ActivityContext, name: string): Promise<string> => {
return `Hello ${name}!`;
};
const helloCities: TOrchestrator = async function* (ctx: OrchestrationContext): any {
let result = "";
result += (yield ctx.callActivity(sayHello, "Tokyo")) + ", ";
ctx.setCustomStatus("Tokyo");
result += (yield ctx.callActivity(sayHello, "London")) + ", ";
ctx.setCustomStatus("London");
result += yield ctx.callActivity(sayHello, "Seattle");
ctx.setCustomStatus("Seattle");
return result;
};
クライアントはオーケストレーション メタデータをポーリングし、 CustomStatus フィールドが "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;
}
import time
from durabletask.azuremanaged.client import DurableTaskSchedulerClient
# Assumes 'client' is a DurableTaskSchedulerClient instance
instance_id = client.schedule_new_orchestration(hello_cities)
state = client.wait_for_orchestration_start(instance_id, fetch_payloads=True)
while state.serialized_custom_status is None or state.serialized_custom_status != '"London"':
time.sleep(0.2)
state = client.get_orchestration_state(instance_id, fetch_payloads=True)
String instanceId = client.scheduleNewOrchestrationInstance("HelloCities");
OrchestrationMetadata metadata = client.waitForInstanceStart(instanceId, Duration.ofMinutes(5), true);
while (!"London".equals(metadata.readCustomStatusAs(String.class))) {
Thread.sleep(200);
metadata = client.getInstanceMetadata(instanceId, true);
}
import { createAzureManagedClient } from "@microsoft/durabletask-js-azuremanaged";
const client = createAzureManagedClient(connectionString);
const instanceId = await client.scheduleNewOrchestration(helloCities);
let state = await client.waitForOrchestrationStart(instanceId, true, 60);
while (!state?.serializedCustomStatus || JSON.parse(state.serializedCustomStatus) !== "London") {
await new Promise((resolve) => setTimeout(resolve, 200));
state = await client.getOrchestrationState(instanceId, true);
}
次のクライアント コードは、オーケストレーションの状態をポーリングし、 CustomStatus が "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;
}
}
const df = require("durable-functions");
module.exports = async function(context, req) {
const client = df.getClient(context);
// Function input comes from the request content.
const eventData = req.body;
const instanceId = await client.startNew(req.params.functionName, undefined, eventData);
context.log(`Started orchestration with ID = '${instanceId}'.`);
let durableOrchestrationStatus = await client.getStatus(instanceId);
while (durableOrchestrationStatus.customStatus.toString() !== "London") {
await new Promise((resolve) => setTimeout(resolve, 200));
durableOrchestrationStatus = await client.getStatus(instanceId);
}
const httpResponseMessage = {
status: 200,
body: JSON.stringify(durableOrchestrationStatus),
};
return httpResponseMessage;
};
注
JavaScript では、次のcustomStatusまたはyieldアクションがスケジュールされると、return フィールドが設定されます。
import json
import logging
import azure.functions as func
import azure.durable_functions as df
from time import sleep
async def main(req: func.HttpRequest, starter: str) -> func.HttpResponse:
client = df.DurableOrchestrationClient(starter)
instance_id = await client.start_new(req.params.functionName, None, None)
logging.info(f"Started orchestration with ID = '{instance_id}'.")
durable_orchestration_status = await client.get_status(instance_id)
while durable_orchestration_status.custom_status != 'London':
sleep(0.2)
durable_orchestration_status = await client.get_status(instance_id)
return func.HttpResponse(body='Success', status_code=200, mimetype='application/json')
注
Pythonでは、次の custom_status または yield アクションがスケジュールされると、return フィールドが設定されます。
カスタム状態のクライアント側ポーリングは、PowerShell SDK では直接サポートされていません。
HTTP 状態 API または Get-DurableStatus コマンドレットを使用して、オーケストレーションの状態を照会します。
@FunctionName("StartHelloCities")
public HttpResponseMessage startHelloCities(
@HttpTrigger(name = "req") HttpRequestMessage<Void> req,
@DurableClientInput(name = "durableContext") DurableClientContext durableContext,
final ExecutionContext context) throws InterruptedException {
DurableTaskClient client = durableContext.getClient();
String instanceId = client.scheduleNewOrchestrationInstance("HelloCities");
context.getLogger().info("Created new Java orchestration with instance ID = " + instanceId);
OrchestrationMetadata metadata;
try {
metadata = client.waitForInstanceStart(instanceId, Duration.ofMinutes(5), true);
} catch (TimeoutException ex) {
return req.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
while (!"London".equals(metadata.readCustomStatusAs(String.class))) {
Thread.sleep(200);
metadata = client.getInstanceMetadata(instanceId, true);
}
return req.createResponseBuilder(HttpStatus.OK).build();
}
カスタム オーケストレーションの状態を使用すると、個別のエンドポイントを構築することなく、構造化されたデータ (パーソナライズされた推奨事項など) をクライアントに返すことができます。 オーケストレーターは入力に基づいてカスタム状態を設定し、クライアントは標準状態 API を介してそれを読み取ります。 これにより、すべてのロジックがサーバー側に留まりますが、クライアント側コードのジェネリックが維持されます。
[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
}
CityRecommender オーケストレータ
const df = require("durable-functions");
module.exports = df.orchestrator(function*(context) {
const userChoice = context.df.getInput();
switch (userChoice) {
case 1:
context.df.setCustomStatus({
recommendedCities: [ "Tokyo", "Seattle" ],
recommendedSeasons: [ "Spring", "Summer" ],
});
break;
case 2:
context.df.setCustomStatus({
recommendedCities: [ "Seattle", "London" ],
recommendedSeasons: [ "Summer" ],
});
break;
case 3:
context.df.setCustomStatus({
recommendedCities: [ "Tokyo", "London" ],
recommendedSeasons: [ "Spring", "Summer" ],
});
break;
}
// Wait for user selection and refine the recommendation
});
CityRecommender オーケストレータ
import azure.functions as func
import azure.durable_functions as df
def orchestrator_function(context: df.DurableOrchestrationContext):
userChoice = int(context.get_input())
if userChoice == 1:
context.set_custom_status({
'recommendedCities': ['Tokyo', 'Seattle'],
'recommendedSeasons': ['Spring', 'Summer']
})
elif userChoice == 2:
context.set_custom_status({
'recommendedCities': ['Seattle', 'London'],
'recommendedSeasons': ['Summer']
})
elif userChoice == 3:
context.set_custom_status({
'recommendedCities': ['Tokyo', 'London'],
'recommendedSeasons': ['Spring', 'Summer']
})
# Wait for user selection and refine the recommendation
main = df.Orchestrator.create(orchestrator_function)
CityRecommender オーケストレータ
param($Context)
$userChoice = $Context.Input -as [int]
if ($userChoice -eq 1) {
Set-DurableCustomStatus -CustomStatus @{ recommendedCities = @('Tokyo', 'Seattle');
recommendedSeasons = @('Spring', 'Summer')
}
}
if ($userChoice -eq 2) {
Set-DurableCustomStatus -CustomStatus @{ recommendedCities = @('Seattle', 'London');
recommendedSeasons = @('Summer')
}
}
if ($userChoice -eq 3) {
Set-DurableCustomStatus -CustomStatus @{ recommendedCities = @('Tokyo', 'London');
recommendedSeasons = @('Spring', 'Summer')
}
}
# Wait for user selection and refine the recommendation
@FunctionName("CityRecommender")
public void cityRecommender(
@DurableOrchestrationTrigger(name = "ctx") TaskOrchestrationContext ctx) {
int userChoice = ctx.getInput(int.class);
switch (userChoice) {
case 1:
ctx.setCustomStatus(new Recommendation(
new String[]{ "Tokyo", "Seattle" },
new String[]{ "Spring", "Summer" }));
break;
case 2:
ctx.setCustomStatus(new Recommendation(
new String[]{ "Seattle", "London" },
new String[]{ "Summer" }));
break;
case 3:
ctx.setCustomStatus(new Recommendation(
new String[]{ "Tokyo", "London" },
new String[]{ "Spring", "Summer" }));
break;
}
// Wait for user selection with an external event
}
class Recommendation {
public Recommendation() { }
public Recommendation(String[] cities, String[] seasons) {
this.recommendedCities = cities;
this.recommendedSeasons = seasons;
}
public String[] recommendedCities;
public String[] recommendedSeasons;
}
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);
}
}
from durabletask import task
def city_recommender(ctx: task.OrchestrationContext, user_choice: int):
if user_choice == 1:
ctx.set_custom_status({
"recommendedCities": ["Tokyo", "Seattle"],
"recommendedSeasons": ["Spring", "Summer"]
})
elif user_choice == 2:
ctx.set_custom_status({
"recommendedCities": ["Seattle", "London"],
"recommendedSeasons": ["Summer"]
})
elif user_choice == 3:
ctx.set_custom_status({
"recommendedCities": ["Tokyo", "London"],
"recommendedSeasons": ["Spring", "Summer"]
})
# Wait for user selection and refine the recommendation
import com.microsoft.durabletask.TaskOrchestration;
import com.microsoft.durabletask.TaskOrchestrationContext;
public class CityRecommender implements TaskOrchestration {
@Override
public void run(TaskOrchestrationContext ctx) {
int userChoice = ctx.getInput(int.class);
switch (userChoice) {
case 1:
ctx.setCustomStatus(new Recommendation(
new String[]{ "Tokyo", "Seattle" },
new String[]{ "Spring", "Summer" }));
break;
case 2:
ctx.setCustomStatus(new Recommendation(
new String[]{ "Seattle", "London" },
new String[]{ "Summer" }));
break;
case 3:
ctx.setCustomStatus(new Recommendation(
new String[]{ "Tokyo", "London" },
new String[]{ "Spring", "Summer" }));
break;
}
// Wait for user selection and refine the recommendation
}
}
class Recommendation {
public Recommendation(String[] cities, String[] seasons) {
this.recommendedCities = cities;
this.recommendedSeasons = seasons;
}
public String[] recommendedCities;
public String[] recommendedSeasons;
}
import { OrchestrationContext, TOrchestrator } from "@microsoft/durabletask-js";
const cityRecommender: TOrchestrator = async function* (ctx: OrchestrationContext, userChoice: number): any {
switch (userChoice) {
case 1:
ctx.setCustomStatus({
recommendedCities: ["Tokyo", "Seattle"],
recommendedSeasons: ["Spring", "Summer"],
});
break;
case 2:
ctx.setCustomStatus({
recommendedCities: ["Seattle", "London"],
recommendedSeasons: ["Summer"],
});
break;
case 3:
ctx.setCustomStatus({
recommendedCities: ["Tokyo", "London"],
recommendedSeasons: ["Spring", "Summer"],
});
break;
}
// Wait for user selection and refine the recommendation
};
アクション可能なデータをクライアントに提供する
このパターンでは、オーケストレーターはカスタム状態を通じて時間の機密情報 (割引、予約 URL、タイムアウトなど) を表示し、一時停止して外部イベントを待機します。 クライアントは、カスタムステータスを読み取ってオファーを表示し、ユーザーが行動したときに確認イベントをオーケストレーターに送り返します。
[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;
}
const df = require("durable-functions");
module.exports = df.orchestrator(function*(context) {
const userId = context.df.getInput();
const discount = yield context.df.callActivity("CalculateDiscount", userId);
context.df.setCustomStatus({
discount,
discountTimeout: 60,
bookingUrl: "https://www.myawesomebookingweb.com",
});
const isBookingConfirmed = yield context.df.waitForExternalEvent("BookingConfirmed");
context.df.setCustomStatus(isBookingConfirmed
? { message: "Thank you for confirming your booking." }
: { message: "The booking was not confirmed on time. Please try again." }
);
return isBookingConfirmed;
});
import azure.functions as func
import azure.durable_functions as df
def orchestrator_function(context: df.DurableOrchestrationContext):
userId = int(context.get_input())
discount = yield context.call_activity('CalculateDiscount', userId)
status = { 'discount' : discount,
'discountTimeout' : 60,
'bookingUrl' : "https://www.myawesomebookingweb.com",
}
context.set_custom_status(status)
is_booking_confirmed = yield context.wait_for_external_event('BookingConfirmed')
context.set_custom_status({'message': 'Thank you for confirming your booking.'} if is_booking_confirmed
else {'message': 'The booking was not confirmed on time. Please try again.'})
return is_booking_confirmed
main = df.Orchestrator.create(orchestrator_function)
param($Context)
$userId = $Context.Input -as [int]
$discount = Invoke-DurableActivity -FunctionName 'CalculateDiscount' -Input $userId
$status = @{
discount = $discount;
discountTimeout = 60;
bookingUrl = "https://www.myawesomebookingweb.com"
}
Set-DurableCustomStatus -CustomStatus $status
$isBookingConfirmed = Invoke-DurableActivity -FunctionName 'BookingConfirmed'
if ($isBookingConfirmed) {
Set-DurableCustomStatus -CustomStatus @{message = 'Thank you for confirming your booking.'}
} else {
Set-DurableCustomStatus -CustomStatus @{message = 'The booking was not confirmed on time. Please try again.'}
}
return $isBookingConfirmed
@FunctionName("ReserveTicket")
public boolean reserveTicket(
@DurableOrchestrationTrigger(name = "ctx") TaskOrchestrationContext ctx) {
String userID = ctx.getInput(String.class);
int discount = ctx.callActivity("CalculateDiscount", userID, int.class).await();
ctx.setCustomStatus(new DiscountInfo(discount, 60, "https://www.myawesomebookingweb.com"));
boolean isConfirmed = ctx.waitForExternalEvent("BookingConfirmed", boolean.class).await();
if (isConfirmed) {
ctx.setCustomStatus("Thank you for confirming your booking.");
} else {
ctx.setCustomStatus("There was a problem confirming your booking. Please try again.");
}
return isConfirmed;
}
class DiscountInfo {
public DiscountInfo() { }
public DiscountInfo(int discount, int discountTimeout, String bookingUrl) {
this.discount = discount;
this.discountTimeout = discountTimeout;
this.bookingUrl = bookingUrl;
}
public int discount;
public int discountTimeout;
public String bookingUrl;
}
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;
}
}
from durabletask import task
def calculate_discount(ctx: task.ActivityContext, user_id: str) -> int:
# Calculate discount based on user
return 10
def reserve_ticket(ctx: task.OrchestrationContext, user_id: str):
discount = yield ctx.call_activity(calculate_discount, input=user_id)
ctx.set_custom_status({
"discount": discount,
"discountTimeout": 60,
"bookingUrl": "https://www.myawesomebookingweb.com"
})
is_booking_confirmed = yield ctx.wait_for_external_event("BookingConfirmed")
if is_booking_confirmed:
ctx.set_custom_status({"message": "Thank you for confirming your booking."})
else:
ctx.set_custom_status({"message": "The booking was not confirmed on time. Please try again."})
return is_booking_confirmed
import com.microsoft.durabletask.TaskOrchestration;
import com.microsoft.durabletask.TaskOrchestrationContext;
public class ReserveTicket implements TaskOrchestration {
@Override
public void run(TaskOrchestrationContext ctx) {
String userId = ctx.getInput(String.class);
int discount = ctx.callActivity("CalculateDiscount", userId, int.class).await();
ctx.setCustomStatus(new DiscountInfo(discount, 60, "https://www.myawesomebookingweb.com"));
boolean isConfirmed = ctx.waitForExternalEvent("BookingConfirmed", boolean.class).await();
if (isConfirmed) {
ctx.setCustomStatus("Thank you for confirming your booking.");
} else {
ctx.setCustomStatus("The booking was not confirmed on time. Please try again.");
}
ctx.complete(isConfirmed);
}
}
class DiscountInfo {
public DiscountInfo(int discount, int discountTimeout, String bookingUrl) {
this.discount = discount;
this.discountTimeout = discountTimeout;
this.bookingUrl = bookingUrl;
}
public int discount;
public int discountTimeout;
public String bookingUrl;
}
import { ActivityContext, OrchestrationContext, TOrchestrator } from "@microsoft/durabletask-js";
const calculateDiscount = async (_: ActivityContext, userId: string): Promise<number> => {
// Calculate discount based on user
return 10;
};
const reserveTicket: TOrchestrator = async function* (ctx: OrchestrationContext, userId: string): any {
const discount: number = yield ctx.callActivity(calculateDiscount, userId);
ctx.setCustomStatus({
discount,
discountTimeout: 60,
bookingUrl: "https://www.myawesomebookingweb.com",
});
const isBookingConfirmed: boolean = yield ctx.waitForExternalEvent("BookingConfirmed");
ctx.setCustomStatus(isBookingConfirmed
? { message: "Thank you for confirming your booking." }
: { message: "The booking was not confirmed on time. Please try again." }
);
return isBookingConfirmed;
};
カスタム オーケストレーションの状態を照会する
前の例では、オーケストレーター コードからカスタム状態を設定する方法を示します。 このセクションでは、外部クライアントがその値を読み取る方法について説明します。
オーケストレーターが SetCustomStatus を呼び出した後、外部クライアントは組み込みのDurable Functions HTTP API を使用して値を照会できます。 例えば次が挙げられます。
GET /runtime/webhooks/durabletask/instances/instance123
応答には、ランタイム メタデータと共に customStatus フィールドが含まれます。
{
"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"
}
オーケストレーション クライアント SDK を使用して、プログラムでカスタム状態のクエリを実行することもできます。 完全なリファレンスについては、「 クエリ インスタンス」を参照してください。
Durable Task SDK では、組み込みの HTTP 状態エンドポイントは提供されません。 代わりに、 DurableTaskClientのオーケストレーション インスタンス メタデータ API を使用して、プログラムでカスタム状態を照会します。
using Microsoft.DurableTask.Client;
OrchestrationMetadata? metadata = await client.GetInstanceAsync(instanceId, getInputsAndOutputs: true);
string? customStatusJson = metadata?.SerializedCustomStatus;
from durabletask.azuremanaged.client import DurableTaskSchedulerClient
# Assumes 'client' is a DurableTaskSchedulerClient instance
state = client.get_orchestration_state(instance_id, fetch_payloads=True)
custom_status_json = state.serialized_custom_status
OrchestrationMetadata metadata = client.getInstanceMetadata(instanceId, true);
CustomStatusPayload payload = metadata.readCustomStatusAs(CustomStatusPayload.class);
import { createAzureManagedClient } from "@microsoft/durabletask-js-azuremanaged";
const client = createAzureManagedClient(connectionString);
// Get the custom status of an orchestration instance
const state = await client.getOrchestrationState(instanceId, true);
const customStatusJson = state?.serializedCustomStatus;
Warnung
カスタム 状態ペイロードは、UTF-16 JSON テキストの 16 KB に制限されています。
次のステップ