Поделиться через


Подоркестрации

Помимо вызова функций активности, функции оркестратора могут вызывать другие функции оркестратора. Например, можно создать большую оркестрацию из библиотеки небольших функций оркестратора. Кроме того, можно параллельно запускать несколько экземпляров функции оркестратора.

Функция оркестратора вызывает другую оркестрационную функцию с помощью API вызова суб-оркестратора. Дополнительные сведения об автоматической повторной попытке см. в разделе "Обработка ошибок" и "Компенсация".

Функции под оркестратора работают так же, как функции действий с точки зрения вызывающего пользователя. Они могут возвращать значение, а родительская функция оркестратора перехватывает любое исключение, которое они вызывают.

Замечание

В среде PowerShell вложенные оркестрации поддерживаются только в автономной версии SDK: AzureFunctions.PowerShell.Durable.SDK. Различия между автономным пакетом SDK и устаревшим встроенным пакетом SDK см. в руководстве по миграции.

Пример

В следующем примере показан сценарий Интернета вещей ("Интернет вещей"), в котором необходимо настроить несколько устройств. Следующая функция представляет рабочий процесс установки, который выполняется для каждого устройства:

Изолированная рабочая модель
public static async Task DeviceProvisioningOrchestration(
    [OrchestrationTrigger] TaskOrchestrationContext context, string deviceId)
{
    // Step 1: Create an installation package in blob storage and return a SAS URL.
    Uri sasUrl = await context.CallActivityAsync<Uri>("CreateInstallationPackage", deviceId);

    // Step 2: Notify the device that the installation package is ready.
    await context.CallActivityAsync("SendPackageUrlToDevice", (deviceId, sasUrl));

    // Step 3: Wait for the device to acknowledge that it has downloaded the new package.
    await context.WaitForExternalEvent<bool>("DownloadCompletedAck");

    // Step 4: ...
}

Модель внутрипроцессного процесса
public static async Task DeviceProvisioningOrchestration(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    string deviceId = context.GetInput<string>();

    // Step 1: Create an installation package in blob storage and return a SAS URL.
    Uri sasUrl = await context.CallActivityAsync<Uri>("CreateInstallationPackage", deviceId);

    // Step 2: Notify the device that the installation package is ready.
    await context.CallActivityAsync("SendPackageUrlToDevice", Tuple.Create(deviceId, sasUrl));

    // Step 3: Wait for the device to acknowledge that it has downloaded the new package.
    await context.WaitForExternalEvent<bool>("DownloadCompletedAck");

    // Step 4: ...
}
using Microsoft.DurableTask;

[DurableTask]
public class DeviceProvisioningOrchestration : TaskOrchestrator<string, object?>
{
    public override async Task<object?> RunAsync(TaskOrchestrationContext context, string deviceId)
    {
        // Step 1: Create an installation package in blob storage and return a SAS URL.
        Uri sasUrl = await context.CallActivityAsync<Uri>("CreateInstallationPackage", deviceId);

        // Step 2: Notify the device that the installation package is ready.
        await context.CallActivityAsync("SendPackageUrlToDevice", (deviceId, sasUrl.ToString()));

        // Step 3: Wait for the device to acknowledge that it has downloaded the new package.
        await context.WaitForExternalEvent<bool>("DownloadCompletedAck");

        // Step 4: ...
        return null;
    }
}

Эту функцию оркестратора можно использовать в текущем виде для одноразовой установки устройства или она может быть частью более крупной оркестрации. В последнем случае родительская функция оркестратора планирует экземпляры DeviceProvisioningOrchestration с помощью API call-sub-orchestrator .

В следующем примере показано, как параллельно выполнять несколько функций оркестратора.

Изолированная рабочая модель
[Function("ProvisionNewDevices")]
public static async Task ProvisionNewDevices(
    [OrchestrationTrigger] TaskOrchestrationContext context)
{
    string[] deviceIds = await context.CallActivityAsync<string[]>("GetNewDeviceIds");

    // Run multiple device provisioning flows in parallel
    var provisioningTasks = new List<Task>();
    foreach (string deviceId in deviceIds)
    {
        Task provisionTask = context.CallSubOrchestratorAsync("DeviceProvisioningOrchestration", deviceId);
        provisioningTasks.Add(provisionTask);
    }

    await Task.WhenAll(provisioningTasks);

    // ...
}

Модель внутрипроцессного процесса
[FunctionName("ProvisionNewDevices")]
public static async Task ProvisionNewDevices(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    string[] deviceIds = await context.CallActivityAsync<string[]>("GetNewDeviceIds");

    // Run multiple device provisioning flows in parallel
    var provisioningTasks = new List<Task>();
    foreach (string deviceId in deviceIds)
    {
        Task provisionTask = context.CallSubOrchestratorAsync("DeviceProvisioningOrchestration", deviceId);
        provisioningTasks.Add(provisionTask);
    }

    await Task.WhenAll(provisioningTasks);

    // ...
}

Замечание

Подоркестрации должны быть определены в том же функциональном приложении, что и родительская оркестрация. Если вам нужно вызвать и ждать оркестрации в другом функциональном приложении, рассмотрите использование встроенной поддержки API HTTP и шаблона опроса HTTP 202. Дополнительные сведения см. в разделе "Функции HTTP".

Дальнейшие действия

using Microsoft.DurableTask;

[DurableTask]
public class ProvisionNewDevices : TaskOrchestrator<object?, object?>
{
    public override async Task<object?> RunAsync(TaskOrchestrationContext context, object? input)
    {
        string[] deviceIds = await context.CallActivityAsync<string[]>("GetNewDeviceIds");

        // Run multiple device provisioning flows in parallel
        var provisioningTasks = new List<Task>();
        foreach (string deviceId in deviceIds)
        {
            Task provisionTask = context.CallSubOrchestratorAsync("DeviceProvisioningOrchestration", deviceId);
            provisioningTasks.Add(provisionTask);
        }

        await Task.WhenAll(provisioningTasks);
        return null;
    }
}

Дальнейшие действия