O status de orquestração personalizado permite anexar metadados JSON arbitrários a uma instância de orquestração em execução para que os clientes externos possam consultá-lo a qualquer momento. Use o status personalizado quando precisar:
-
Relatar o progresso no meio do voo – permitir que uma interface do usuário mostre qual etapa uma orquestração atingiu sem esperar que ela seja concluída.
-
Retornar dados dinâmicos aos chamadores — exibir recomendações, informações de desconto ou instruções para a próxima etapa enquanto a orquestração ainda está em execução.
-
Coordenar com sistemas externos – compartilhe o estado para que outros serviços ou operadores humanos possam consultar e agir.
Aviso
A carga de status personalizada é limitada a 16 KB de texto JSON UTF-16. Se você precisar de uma carga útil maior, utilize o armazenamento externo e armazene uma referência (como um URL de blob) no estado personalizado.
Em Azure Functions, esse status está disponível por meio da API GetStatus HTTP ou SDK API equivalente no objeto cliente de orquestração.
Em SDKs de Tarefa Durável, esse status está disponível por meio de APIs de consulta de status de orquestração no DurableTaskClient (por exemplo, GetInstanceAsync em .NET ou getInstanceMetadata em Java).
Importante
Atualmente, o SDK da Tarefa Durável do PowerShell não está disponível.
Exemplos de casos de uso para status personalizado de orquestração
A tabela a seguir resume padrões comuns. Selecione um caso de uso para ir para o exemplo correspondente.
Visualizar o progresso da orquestração
Nesse padrão, o orquestrador chama SetCustomStatus (ou o equivalente em seu idioma) depois que cada atividade é concluída, atualizando o status com o nome da última cidade completada. Um cliente consulta o endpoint de status, lê o estado atual e atualiza um indicador de progresso na IU.
O exemplo a seguir demonstra como compartilhar progresso usando o endpoint de status HTTP das Durable Functions:
Observação
Esses exemplos são escritos para Durable Functions 2.x e não são compatíveis com Durable Functions 1.x. Para obter mais informações sobre as diferenças entre as versões, consulte o artigo Durable Functions versions.
[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}!";
}
Função de orquestrador 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 função de atividade:
module.exports = async function(context, name) {
return `Hello ${name}!`;
};
E1_HelloSequence Função de Orquestrador
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 Função de atividade
def main(name: str) -> str:
return f"Hello {name}!"
E1_HelloSequence Função de Orquestrador
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 Função de atividade
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);
}
O exemplo a seguir demonstra o compartilhamento de progresso usando as APIs de cliente do SDK de Tarefa Durável:
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;
};
O SDK da Tarefa Durável não está disponível para o PowerShell. Use Durable Functions em vez disso.
O cliente pode sondar metadados de orquestração e aguardar até que o CustomStatus campo seja definido como "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);
}
O SDK da Tarefa Durável não está disponível para o PowerShell. Use Durable Functions em vez disso.
O código do cliente a seguir monitora o status de orquestração e aguarda até que CustomStatus seja configurado para "London" antes de retornar uma resposta.
[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;
};
Observação
No JavaScript, o customStatus campo é definido quando a próxima yield ou return ação é agendada.
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')
Observação
Em Python, o campo custom_status é definido quando a próxima ação yield ou return está agendada.
A sondagem do status personalizado no lado do cliente não é diretamente suportada no SDK do PowerShell. Use a API de status HTTP ou o Get-DurableStatus cmdlet para consultar o status da orquestração.
@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();
}
Você pode usar o status de orquestração personalizado para retornar dados estruturados, como recomendações personalizadas, para clientes sem criar endpoints separados. O orquestrador define o status personalizado com base na entrada e o cliente o lê por meio da API de status padrão. Isso mantém o código do lado do cliente genérico enquanto toda a lógica permanece no lado do servidor.
[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 Orquestrador
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 Orquestrador
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 Orquestrador
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
};
O SDK da Tarefa Durável não está disponível para o PowerShell. Use Durable Functions em vez disso.
Fornecer dados acionáveis aos clientes
Nesse padrão, o orquestrador exibe informações sensíveis ao tempo — como um desconto, uma URL de reserva e um tempo limite — por meio do status personalizado e, em seguida, pausa para aguardar um evento externo. Um cliente lê o status personalizado para exibir a oferta e envia o evento de confirmação de volta ao orquestrador quando o usuário age.
[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;
};
O SDK da Tarefa Durável não está disponível para o PowerShell. Use Durable Functions em vez disso.
Consultar o status da orquestração personalizada
Os exemplos anteriores mostram como definir o status personalizado do código do orquestrador. Esta seção se concentra em como os clientes externos leem esse valor.
Depois que um orquestrador chama SetCustomStatus, os clientes externos podem consultar o valor por meio da API HTTP Durable Functions interna. Por exemplo:
GET /runtime/webhooks/durabletask/instances/instance123
A resposta inclui o customStatus campo junto com metadados de 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"
}
Você também pode consultar o status personalizado programaticamente usando o SDK do cliente de orquestração. Para obter uma referência completa, consulte instâncias de consulta.
Os SDKs de Tarefas Duráveis não fornecem um ponto de extremidade de status HTTP integrado. Em vez disso, consulta programaticamente o estado personalizado usando APIs de metadados da instância de orquestração no DurableTaskClient.
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;
O SDK da Tarefa Durável não está disponível para o PowerShell. Use Durable Functions em vez disso.
Aviso
A carga de status personalizada é limitada a 16 KB de texto JSON UTF-16.
Próximas Etapas