Цепочка функций — это паттерн, при котором выполняется последовательность функций в заданном порядке. Обычно выходные данные одной функции передаются в входные данные следующей функции. В этой статье описывается последовательность вызовов, которая создается при выполнении руководства по началу работы с Durable Functions (C#, JavaScript, TypeScript, Python, PowerShell или Java). Дополнительные сведения см. в обзоре Durable Functions.
Предварительные условия
Модель программирования версии 3
Модель программирования версии 4
Цепочка функций — это шаблон, в котором выполняется последовательность действий в порядке. Обычно выходные данные одного действия передаются в входные данные следующего. В этой статье описывается последовательность вызовов для SDK Durable Task для .NET, JavaScript, Python и Java.
Функции
В этой статье описаны эти функции в примере приложения:
-
E1_HelloSequence: функция оркестратора , которая вызывает E1_SayHello несколько раз в последовательности. Он сохраняет все выходные данные и записывает результаты.
-
E1_SayHello: функция действия , которая добавляет "Hello" в начало строки.
-
HttpStart: функция устойчивого клиента , активироваемая HTTP, которая запускает экземпляр оркестратора.
В этой статье описываются эти компоненты в примере приложения:
-
GreetingOrchestration, greetingOrchestrator, function_chaining_orchestrator или ActivityChaining: оркестратор, который вызывает несколько действия по порядку. Он сохраняет все выходные данные и записывает результаты.
- Функции действий: действия, которые обрабатывают входные данные и возвращают результаты. Каждое действие выполняет простое преобразование входных данных.
- Клиент: клиентское приложение, которое запускает экземпляр оркестратора и ожидает результата.
Orchestrator
[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"));
outputs.Add(await context.CallActivityAsync<string>("E1_SayHello", "Seattle"));
outputs.Add(await context.CallActivityAsync<string>("E1_SayHello_DirectInput", "London"));
// returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
return outputs;
}
Все функции оркестрации C# должны иметь параметр типа DurableOrchestrationContext, который существует в сборке Microsoft.Azure.WebJobs.Extensions.DurableTask. Этот объект контекста позволяет вызывать другие функции действия и передавать им входные параметры с помощью метода CallActivityAsync.
Этот код трижды последовательно вызывает E1_SayHello с разными значениями параметров. Значение, возвращаемое при каждом вызове, добавляется в список outputs, который возвращается в конце функции.
Модель программирования версии 3
function.json
Если вы разрабатываете в Visual Studio Code или на портале Azure, вот файл оркестратора function.json.
{
"bindings": [
{
"name": "context",
"type": "orchestrationTrigger",
"direction": "in"
}
],
"disabled": false
}
Параметр ключа — это тип привязки orchestrationTrigger . Во всех функциях оркестратора должен использоваться такой тип триггера.
Предупреждение
Чтобы следовать правилу "без ввода-вывода" для функций оркестратора, не используйте входные или выходные привязки с привязкой триггера orchestrationTrigger . Если вам нужны другие входные или выходные привязки, используйте их в activityTrigger функциях, которые вызывает оркестратор. Дополнительные сведения см. в разделе об ограничениях кода функции оркестратора.
index.js
Функция оркестратора:
const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
context.log("Starting chain sample");
const output = [];
output.push(yield context.df.callActivity("E1_SayHello", "Tokyo"));
output.push(yield context.df.callActivity("E1_SayHello", "Seattle"));
output.push(yield context.df.callActivity("E1_SayHello", "London"));
return output;
});
Все функции оркестратора на JavaScript должны содержать модуль durable-functions. Это библиотека, которая позволяет писать Durable Functions в JavaScript. Три основных различия между функцией оркестратора и другими функциями JavaScript:
- Функция оркестратора является функцией генератора.
- Эта функция упаковывается в вызов к методу
durable-functions модуля orchestrator (в нашем примере это df).
- Функция синхронна.
orchestrator Так как метод вызываетcontext.done, функция возвращается.
Объект context содержит объект контекста устойчивой оркестровки df, что позволяет вызывать другие функции активностей и передавать им входные параметры с помощью метода callActivity. Этот код вызывает E1_SayHello три раза подряд с разными значениями параметров, используя yield для указания, что выполнение должно ожидать возврата из асинхронных вызовов функций. Значение, возвращаемое при каждом вызове, добавляется в массив outputs, который возвращается при завершении функции.
Модель программирования версии 4
const df = require("durable-functions");
const helloActivityName = "sayHello";
df.app.orchestration("helloSequence", function* (context) {
context.log("Starting chain sample");
const output = [];
output.push(yield context.df.callActivity(helloActivityName, "Tokyo"));
output.push(yield context.df.callActivity(helloActivityName, "Seattle"));
output.push(yield context.df.callActivity(helloActivityName, "Cairo"));
return output;
});
Все функции оркестратора на JavaScript должны содержать модуль durable-functions. Этот модуль позволяет записывать Durable Functions в JavaScript. Чтобы использовать модель программирования узлов V4, необходимо установить v3.x версию durable-functions.
Два ключевых различия между функцией оркестратора и другими функциями JavaScript:
- Функция оркестратора является функцией генератора.
- Функция синхронна. Функция возвращается.
Объект context содержит объект контекста устойчивой оркестровки df, что позволяет вызывать другие функции активностей и передавать им входные параметры с помощью метода callActivity. Этот код вызывает sayHello три раза подряд с разными значениями параметров, используя yield для указания, что выполнение должно ожидать возврата из асинхронных вызовов функций. Значение, возвращаемое при каждом вызове, добавляется в массив outputs, который возвращается при завершении функции.
Примечание.
Python Durable Functions доступны только для среды выполнения Функций 3.0.
function.json
Если вы используете Visual Studio Code или портал Azure для разработки, вот содержимое файла function.json для функции оркестратора. Для большинства функций оркестратора файл function.json будет выглядеть почти так же.
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "context",
"type": "orchestrationTrigger",
"direction": "in"
}
]
}
Самое важное здесь — это тип привязки orchestrationTrigger. Во всех функциях оркестратора должен использоваться такой тип триггера.
Предупреждение
Чтобы не нарушать требование "без ввода и вывода", применяемое к функциям оркестратора, не используйте никакие привязки для ввода или вывода данных, когда используете триггерное связывание orchestrationTrigger. Если вам нужны входные или выходные привязки, используйте их в контексте функций activityTrigger, которые вызываются оркестратором. Дополнительные сведения см. в статье об ограничениях кода функции оркестратора.
__init__.py
Функция оркестратора:
import azure.functions as func
import azure.durable_functions as df
def orchestrator_function(context: df.DurableOrchestrationContext):
result1 = yield context.call_activity('E1_SayHello', "Tokyo")
result2 = yield context.call_activity('E1_SayHello', "Seattle")
result3 = yield context.call_activity('E1_SayHello', "London")
return [result1, result2, result3]
main = df.Orchestrator.create(orchestrator_function)
Все функции оркестрации Python должны включать пакет durable-functions. Это библиотека, которая позволяет писать Durable Functions в Python. Два основных различия между функцией оркестратора и другими функциями Python:
- Функция оркестратора является функцией генератора.
-
Файл регистрирует функцию оркестратора, указывая
main = df.Orchestrator.create(<orchestrator function name>) в конце файла. Это помогает отличить его от других вспомогательных функций, объявленных в файле.
Этот объект context позволяет вызывать другие функции действия и передавать им входные параметры с помощью метода call_activity. Этот код вызывает E1_SayHello три раза подряд с разными значениями параметров, используя yield для указания, что выполнение должно ожидать возврата из асинхронных вызовов функций. Возвратное значение каждого вызова получаем в конце выполнения функции.
Пример PowerShell еще недоступен.
Java пример еще недоступен.
В этом коде показан оркестратор, который вызывает три действия в последовательности и передает каждый вывод в следующее действие:
using System.Threading.Tasks;
using Microsoft.DurableTask;
[DurableTask]
public class GreetingOrchestration : TaskOrchestrator<string, string>
{
public override async Task<string> RunAsync(TaskOrchestrationContext context, string name)
{
// Step 1: Say hello to the person
string greeting = await context.CallActivityAsync<string>(nameof(SayHelloActivity), name);
// Step 2: Process the greeting
string processedGreeting = await context.CallActivityAsync<string>(nameof(ProcessGreetingActivity), greeting);
// Step 3: Finalize the response
string finalResponse = await context.CallActivityAsync<string>(nameof(FinalizeResponseActivity), processedGreeting);
return finalResponse;
}
}
Все оркестраторы .NET наследуются от TaskOrchestrator<TInput, TOutput>. Элемент TaskOrchestrationContext позволяет вызывать действия с помощью CallActivityAsync. Код вызывает три действия в последовательности, где каждое действие получает выходные данные предыдущего действия.
В следующем коде показан оркестратор, вызывающий три действия в последовательности:
import {
OrchestrationContext,
TOrchestrator,
} from "@microsoft/durabletask-js";
const greetingOrchestrator: TOrchestrator = async function* (
ctx: OrchestrationContext,
name: string
): any {
// Step 1: Say hello to the person
const greeting: string = yield ctx.callActivity(sayHello, name);
// Step 2: Process the greeting
const processedGreeting: string = yield ctx.callActivity(processGreeting, greeting);
// Step 3: Finalize the response
const finalResponse: string = yield ctx.callActivity(finalizeResponse, processedGreeting);
return finalResponse;
};
Все оркестраторы JavaScript — это функции генераторов (async function*), которые используют yield для вызова действий. Метод контекста оркестрации callActivity планирует выполнение активности. Код вызывает три действия последовательно, передавая выходные данные каждого действия следующему.
В следующем коде показан оркестратор, вызывающий три действия в последовательности:
from durabletask import task
# Orchestrator function
def function_chaining_orchestrator(ctx: task.OrchestrationContext, name: str) -> str:
"""Orchestrator that demonstrates function chaining pattern."""
# Call first activity
greeting = yield ctx.call_activity(say_hello, input=name)
# Call second activity with the result from first activity
processed_greeting = yield ctx.call_activity(process_greeting, input=greeting)
# Call third activity with the result from second activity
final_response = yield ctx.call_activity(finalize_response, input=processed_greeting)
return final_response
Все Python оркестраторы — это функции генератора, использующие yield для вызова действий. Метод контекста оркестрации call_activity планирует выполнение активности. Код вызывает три действия последовательно, передавая выходные данные каждого действия следующему.
Этот пример показан для .NET, JavaScript, Java и Python.
В следующем коде показан оркестратор, вызывающий три действия в последовательности:
import com.microsoft.durabletask.DurableTaskGrpcWorker;
import com.microsoft.durabletask.DurableTaskSchedulerWorkerExtensions;
import com.microsoft.durabletask.TaskOrchestration;
import com.microsoft.durabletask.TaskOrchestrationFactory;
DurableTaskGrpcWorker worker = DurableTaskSchedulerWorkerExtensions.createWorkerBuilder(connectionString)
.addOrchestration(new TaskOrchestrationFactory() {
@Override
public String getName() { return "ActivityChaining"; }
@Override
public TaskOrchestration create() {
return ctx -> {
String input = ctx.getInput(String.class);
// Call activities in sequence, passing output from one to the next
String x = ctx.callActivity("Reverse", input, String.class).await();
String y = ctx.callActivity("Capitalize", x, String.class).await();
String z = ctx.callActivity("ReplaceWhitespace", y, String.class).await();
ctx.complete(z);
};
}
})
.build();
В Java оркестраторы определяются с помощью TaskOrchestrationFactory. Метод контекста callActivity планирует выполнение действия и await() ожидает результата. Код вызывает три действия последовательно, передавая выходные данные каждого действия следующему.
Activity
[FunctionName("E1_SayHello")]
public static string SayHello([ActivityTrigger] IDurableActivityContext context)
{
string name = context.GetInput<string>();
return $"Hello {name}!";
}
Действия используют атрибут ActivityTrigger. Используйте IDurableActivityContext для выполнения действий, таких как чтение входных данных с помощью GetInput<T>.
E1_SayHello форматирует строку приветствия.
Вместо привязки к IDurableActivityContext, привязывайтесь напрямую к типу, передаваемому в функцию. Например:
[FunctionName("E1_SayHello_DirectInput")]
public static string SayHelloDirectInput([ActivityTrigger] string name)
{
return $"Hello {name}!";
}
Модель программирования версии 3
E1_SayHello/function.json
Файл Function.json для функции действия E1_SayHello будет таким же, как и для E1_HelloSequence, с одним исключением: в нем используется тип привязки activityTrigger вместо orchestrationTrigger.
{
"bindings": [
{
"name": "name",
"type": "activityTrigger",
"direction": "in"
}
],
"disabled": false
}
Примечание.
Используйте привязку activityTrigger для всех функций действий, которые вызываются функцией оркестрации.
Функция E1_SayHello реализует достаточно простую операцию форматирования строки.
E1_SayHello/index.js
module.exports = function (context) {
context.done(null, `Hello ${context.bindings.name}!`);
};
В отличие от функции оркестрации, функция действия не требует специальной настройки. Оркестратор передает входные данные объекта context.bindings под именем привязки activityTrigger . В данном случае context.bindings.name. Задайте имя привязки в качестве параметра экспортируемой функции, чтобы получить к ней доступ напрямую, как и в примере.
Модель программирования версии 4
sayHello форматирует строку приветствия.
const df = require("durable-functions");
const helloActivityName = "sayHello";
df.app.activity(helloActivityName, {
handler: function (input) {
return `Hello ${input}`;
},
});
В отличие от функции оркестрации, функция действия не требует специальной настройки. Оркестратор передает входные данные в качестве первого аргумента функции. Второй аргумент — это контекст вызова, который не используется в этом примере.
E1_SayHello/function.json
Файл Function.json для функции действия E1_SayHello будет таким же, как и для E1_HelloSequence, с одним исключением: в нем используется тип привязки activityTrigger вместо orchestrationTrigger.
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "name",
"type": "activityTrigger",
"direction": "in"
}
]
}
Примечание.
Для любой функции действия, которую вызывает функция оркестрации, должна использоваться привязка activityTrigger.
Функция E1_SayHello реализует достаточно простую операцию форматирования строки.
E1_SayHello/__init__.py
def main(name: str) -> str:
return f"Hello {name}!"
В отличие от функции оркестратора, для функции активности не требуется специальной настройки. Входные данные, передаваемые ей функцией оркестратора, напрямую доступны в качестве параметра функции.
Пример PowerShell скоро появится.
Пример Java скоро появится.
Действия в пакете SDK для устойчивых задач наследуются от TaskActivity<TInput, TOutput>:
using System.Threading.Tasks;
using Microsoft.DurableTask;
using Microsoft.Extensions.Logging;
[DurableTask]
public class SayHelloActivity : TaskActivity<string, string>
{
private readonly ILogger<SayHelloActivity> _logger;
public SayHelloActivity(ILogger<SayHelloActivity> logger)
{
_logger = logger;
}
public override Task<string> RunAsync(TaskActivityContext context, string name)
{
_logger.LogInformation("Activity SayHello called with name: {Name}", name);
return Task.FromResult($"Hello {name}!");
}
}
[DurableTask]
public class ProcessGreetingActivity : TaskActivity<string, string>
{
public override Task<string> RunAsync(TaskActivityContext context, string greeting)
{
return Task.FromResult($"{greeting} How are you today?");
}
}
[DurableTask]
public class FinalizeResponseActivity : TaskActivity<string, string>
{
public override Task<string> RunAsync(TaskActivityContext context, string response)
{
return Task.FromResult($"{response} I hope you're doing well!");
}
}
Используйте внедрение зависимостей для получения таких сервисов, как ILogger.
[DurableTask] Добавьте атрибут для регистрации действия в рабочей роли.
Действия в пакете SDK для устойчивых задач — это простые функции:
import { ActivityContext } from "@microsoft/durabletask-js";
const sayHello = async (_ctx: ActivityContext, name: string): Promise<string> => {
return `Hello ${name}!`;
};
const processGreeting = async (_ctx: ActivityContext, greeting: string): Promise<string> => {
return `${greeting} How are you today?`;
};
const finalizeResponse = async (_ctx: ActivityContext, response: string): Promise<string> => {
return `${response} I hope you're doing well!`;
};
В отличие от оркестраторов, действия могут выполнять операции ввода-вывода. К таким операциям относятся вызовы HTTP, запросы к базе данных и доступ к файлам. Входные данные передаются непосредственно в качестве параметра.
Действия в пакете SDK для устойчивых задач — это простые функции:
from durabletask import task
def say_hello(ctx: task.ActivityContext, name: str) -> str:
"""First activity that greets the user."""
return f"Hello {name}!"
def process_greeting(ctx: task.ActivityContext, greeting: str) -> str:
"""Second activity that processes the greeting."""
return f"{greeting} How are you today?"
def finalize_response(ctx: task.ActivityContext, response: str) -> str:
"""Third activity that finalizes the response."""
return f"{response} I hope you're doing well!"
В отличие от оркестраторов, действия могут выполнять операции ввода-вывода. К таким операциям относятся вызовы HTTP, запросы к базе данных и доступ к файлам. Входные данные передаются непосредственно в качестве параметра.
Этот пример показан для .NET, JavaScript, Java и Python.
Действия в Java определяются с помощью TaskActivityFactory:
import com.microsoft.durabletask.TaskActivity;
import com.microsoft.durabletask.TaskActivityFactory;
.addActivity(new TaskActivityFactory() {
@Override
public String getName() { return "Reverse"; }
@Override
public TaskActivity create() {
return ctx -> {
String input = ctx.getInput(String.class);
StringBuilder builder = new StringBuilder(input);
builder.reverse();
return builder.toString();
};
}
})
.addActivity(new TaskActivityFactory() {
@Override
public String getName() { return "Capitalize"; }
@Override
public TaskActivity create() {
return ctx -> ctx.getInput(String.class).toUpperCase();
}
})
.addActivity(new TaskActivityFactory() {
@Override
public String getName() { return "ReplaceWhitespace"; }
@Override
public TaskActivity create() {
return ctx -> {
String input = ctx.getInput(String.class);
return input.trim().replaceAll("\\s", "-");
};
}
})
Зарегистрируйте каждое действие с помощью конструктора заданий addActivity. Действия могут выполнять операции ввода-вывода и возвращать результаты оркестратору.
Клиент
Запустите экземпляр функции оркестратора из клиентской функции. Используйте функцию HttpStart, запускаемую по HTTP-запросу, для создания экземпляров E1_HelloSequence.
public static class HttpStart
{
[FunctionName("HttpStart")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}")] HttpRequestMessage req,
[DurableClient] IDurableClient starter,
string functionName,
ILogger log)
{
// Function input comes from the request content.
object eventData = await req.Content.ReadAsAsync<object>();
string instanceId = await starter.StartNewAsync(functionName, eventData);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return starter.CreateCheckStatusResponse(req, instanceId);
}
}
Чтобы взаимодействовать с оркестраторами, добавьте входную привязку DurableClient . Используйте клиент для запуска оркестрации и возврата HTTP-ответа, включающего URL-адреса для проверки состояния новой оркестрации.
Модель программирования версии 3
HttpStart/function.json
{
"bindings": [
{
"authLevel": "anonymous",
"name": "req",
"type": "httpTrigger",
"direction": "in",
"route": "orchestrators/{functionName}",
"methods": ["post"]
},
{
"name": "$return",
"type": "http",
"direction": "out"
},
{
"name": "starter",
"type": "orchestrationClient",
"direction": "in"
}
],
"disabled": false
}
Чтобы взаимодействовать с оркестраторами, добавьте входную привязку durableClient .
HttpStart/index.js
const df = require("durable-functions");
module.exports = async function (context, req) {
const client = df.getClient(context);
const instanceId = await client.startNew(req.params.functionName, undefined, req.body);
context.log(`Started orchestration with ID = '${instanceId}'.`);
return client.createCheckStatusResponse(context.bindingData.req, instanceId);
};
Используется df.getClient для получения DurableOrchestrationClient объекта. Используйте клиент для запуска оркестрации и возврата HTTP-ответа, включающего URL-адреса для проверки состояния новой оркестрации.
Модель программирования версии 4
const df = require("durable-functions");
const { app } = require("@azure/functions");
app.http("httpStart", {
route: "orchestrators/{orchestratorName}",
extraInputs: [df.input.durableClient()],
handler: async (request, context) => {
const client = df.getClient(context);
const body = await request.json();
const instanceId = await client.startNew(request.params.orchestratorName, { input: body });
context.log(`Started orchestration with ID = '${instanceId}'.`);
return client.createCheckStatusResponse(request, instanceId);
},
});
Чтобы управлять оркестраторами и взаимодействовать с ними, добавьте входную привязку durableClient . Укажите привязку в аргументе extraInputs при регистрации функции. Получение входных durableClient данных путем вызова df.input.durableClient().
Используется df.getClient для получения DurableClient объекта. Используйте клиент для запуска оркестрации и возврата HTTP-ответа, включающего URL-адреса для проверки состояния новой оркестрации.
HttpStart/function.json
{
"scriptFile": "__init__.py",
"bindings": [
{
"authLevel": "anonymous",
"name": "req",
"type": "httpTrigger",
"direction": "in",
"route": "orchestrators/{functionName}",
"methods": [
"post",
"get"
]
},
{
"name": "$return",
"type": "http",
"direction": "out"
},
{
"name": "starter",
"type": "durableClient",
"direction": "in"
}
]
}
Для взаимодействия с оркестраторами функция должна включать входную привязку durableClient.
HttpStart/__init__.py
import logging
import azure.functions as func
import azure.durable_functions as df
async def main(req: func.HttpRequest, starter: str) -> func.HttpResponse:
client = df.DurableOrchestrationClient(starter)
instance_id = await client.start_new(req.route_params["functionName"], None, None)
logging.info(f"Started orchestration with ID = '{instance_id}'.")
return client.create_check_status_response(req, instance_id)
Используйте конструктор DurableOrchestrationClient для создания клиента Durable Functions. Используйте клиент для запуска оркестрации и возврата HTTP-ответа, включающего URL-адреса для проверки состояния новой оркестрации.
Пример PowerShell скоро появится.
Пример Java скоро появится.
Запустите оркестрацию из клиентского приложения. Клиент планирует оркестрацию и может ждать завершения.
using System;
using Microsoft.DurableTask.Client;
// Create the client
var client = DurableTaskClientBuilder.UseDurableTaskScheduler(connectionString).Build();
// Schedule a new orchestration instance
string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(
nameof(GreetingOrchestration),
input: "World");
Console.WriteLine($"Started orchestration with ID: {instanceId}");
// Wait for the orchestration to complete
OrchestrationMetadata result = await client.WaitForInstanceCompletionAsync(
instanceId,
getInputsAndOutputs: true);
Console.WriteLine($"Orchestration completed with result: {result.ReadOutputAs<string>()}");
Создайте DurableTaskClient с помощью строки подключения к планировщику устойчивых задач. Используйте ScheduleNewOrchestrationInstanceAsync для запуска оркестрации и WaitForInstanceCompletionAsync для ожидания завершения.
import {
DurableTaskAzureManagedClientBuilder,
} from "@microsoft/durabletask-js-azuremanaged";
const connectionString =
process.env.DURABLE_TASK_SCHEDULER_CONNECTION_STRING ||
"Endpoint=http://localhost:8080;Authentication=None;TaskHub=default";
const client = new DurableTaskAzureManagedClientBuilder()
.connectionString(connectionString)
.build();
// Schedule a new orchestration instance
const instanceId = await client.scheduleNewOrchestration(greetingOrchestrator, "World");
console.log(`Started orchestration with ID: ${instanceId}`);
// Wait for the orchestration to complete
const state = await client.waitForOrchestrationCompletion(instanceId, true, 30);
console.log(`Orchestration completed with result: ${state?.serializedOutput}`);
Создайте DurableTaskAzureManagedClientBuilder с помощью строки подключения к планировщику устойчивых задач. Используйте scheduleNewOrchestration для запуска оркестрации и waitForOrchestrationCompletion для ожидания завершения.
from durabletask.azuremanaged.client import DurableTaskSchedulerClient
# Create the client
client = DurableTaskSchedulerClient(
host_address=endpoint,
secure_channel=endpoint != "http://localhost:8080",
taskhub=taskhub_name,
token_credential=credential
)
# Schedule a new orchestration instance
instance_id = client.schedule_new_orchestration(
function_chaining_orchestrator,
input="World"
)
print(f"Started orchestration with ID: {instance_id}")
# Wait for the orchestration to complete
result = client.wait_for_orchestration_completion(instance_id, timeout=60)
if result and result.runtime_status == "COMPLETED":
print(f"Orchestration completed with result: {result.serialized_output}")
Подключение DurableTaskSchedulerClient к планировщику устойчивых задач. Используйте schedule_new_orchestration для запуска оркестрации и wait_for_orchestration_completion для ожидания завершения.
Этот пример показан для .NET, JavaScript, Java и Python.
import java.time.Duration;
import com.microsoft.durabletask.DurableTaskClient;
import com.microsoft.durabletask.NewOrchestrationInstanceOptions;
import com.microsoft.durabletask.OrchestrationMetadata;
import com.microsoft.durabletask.azuremanaged.DurableTaskSchedulerClientExtensions;
// Create the client
DurableTaskClient client = DurableTaskSchedulerClientExtensions
.createClientBuilder(connectionString)
.build();
// Schedule a new orchestration instance
String instanceId = client.scheduleNewOrchestrationInstance(
"ActivityChaining",
new NewOrchestrationInstanceOptions().setInput("Hello, world!"));
System.out.println("Started orchestration with ID: " + instanceId);
// Wait for the orchestration to complete
OrchestrationMetadata result = client.waitForInstanceCompletion(
instanceId,
Duration.ofSeconds(30),
true);
System.out.println("Orchestration completed with result: " + result.readOutputAs(String.class));
Создайте DurableTaskClient с помощью connection string. Используйте scheduleNewOrchestrationInstance для запуска оркестрации и waitForInstanceCompletion для ожидания завершения.
Запустите пример
Чтобы запустить E1_HelloSequence оркестрацию, отправьте этот POST-запрос HTTP в функцию HttpStart.
POST http://{host}/orchestrators/E1_HelloSequence
Примечание.
Предыдущий фрагмент кода HTTP предполагает, что в файле host.json образца удален стандартный префикс api/ из всех URL-адресов функций HTTP-триггеров. Найдите эту конфигурацию в файлеhost.json примера.
Например, если вы используете пример в приложении-функции с именем myfunctionapp, замените {host} на myfunctionapp.azurewebsites.net.
Запрос возвращает HTTP 202 (обрезанный для краткости):
HTTP/1.1 202 Accepted
Content-Length: 719
Content-Type: application/json; charset=utf-8
Location: http://{host}/runtime/webhooks/durabletask/instances/96924899c16d43b08a536de376ac786b?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}
(...trimmed...)
Очередь оркестрации формируется и немедленно запускается. Используйте URL-адрес в заголовке Location , чтобы проверить состояние выполнения.
GET http://{host}/runtime/webhooks/durabletask/instances/96924899c16d43b08a536de376ac786b?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}
Ответ показывает состояние оркестрации. Так как это происходит быстро, экземпляр часто находится в состоянии «Завершено» и возвращает ответ в сокращённом виде.
HTTP/1.1 200 OK
Content-Length: 179
Content-Type: application/json; charset=utf-8
{"runtimeStatus":"Completed","input":null,"output":["Hello Tokyo!","Hello Seattle!","Hello London!"],"createdTime":"2017-06-29T05:24:57Z","lastUpdatedTime":"2017-06-29T05:24:59Z"}
Экземпляр runtimeStatusзавершен и output содержит сериализованный в формате JSON результат выполнения функции оркестратора.
Примечание.
Реализуйте аналогичную логику запуска для других типов триггеров, например queueTrigger, eventHubTriggerили timerTrigger.
Просмотрите журналы выполнения функции. Функция E1_HelloSequence запускается и завершается несколько раз из-за поведения воспроизведения, описанного в устойчивости работы оркестрации. Но E1_SayHello запускается только три раза, так как вызовы функции действия не повторяются.
Чтобы запустить пример, вам потребуется:
Запустите эмулятор планировщика устойчивых задач (для локальной разработки):
docker run -d -p 8080:8080 -p 8082:8082 --name dts-emulator mcr.microsoft.com/dts/dts-emulator:latest
Запустите рабочий процесс , чтобы зарегистрировать оркестратор и операции.
Запустите клиент , чтобы запланировать оркестрацию и дождаться результата.
Вывод клиента демонстрирует результат последовательной оркестрации:
Started orchestration with ID: abc123
Orchestration completed with result: "Hello World! How are you today? I hope you're doing well!"
Журналы рабочих ролей показывают, что каждое действие выполняется в последовательности и передает выходные данные в следующее действие.
Следующие шаги
В этом примере демонстрируется простая оркестрация цепочки функций. Далее реализуйте шаблон масштабирования fan-out/fan-in.