如何确保在持久函数中整个编排序列之后出现“已完成”日志

问题描述 投票:0回答:2

我正在开发一个持久功能设置,其中有一个计时器触发器来编排一系列活动。但是,我遇到了记录顺序的问题。目前,“已完成”日志在计时器触发后立即出现,但我希望它仅在整个编排序列(包括所有子编排)完成后才出现。下面是我的代码的简化版本:



[Function("TimerTrigger_EveryMinute")]
public async Task TimerTrigger_EveryMinute(
    [TimerTrigger("0 * * * * *")] TimerInfo timerInfo,
    [DurableClient] DurableTaskClient starter)
{
    _logger.LogError($"Running timer trigger");

    string instanceId = await starter.StartNewAsync("MainOrchestrator", null);

    // Wait for the entire orchestration to complete
    await starter.WaitForInstanceCompletionAsync(instanceId);

    _logger.LogError($"Completed timer trigger orchestration with ID = '{instanceId}'");
}

[Function("MainOrchestrator")]
public async Task MainOrchestrator(
    [OrchestrationTrigger] DurableOrchestrationContext context)
{
    _logger.LogError($"Running MainOrchestrator");

    var tasks = new List<Task>();

    List<TransactionData> transactions = new List<TransactionData>();

    // Call suborchestrator for each ongoing transaction
    foreach (var transaction in transactions)
    {
        tasks.Add(context.CallSubOrchestratorAsync("SubOrchestrator", transaction));
    }

    await Task.WhenAll(tasks);
}

[Function("SubOrchestrator")]
public async Task SubOrchestrator(
    [OrchestrationTrigger] DurableOrchestrationContext context, TransactionData transaction)
{
    _logger.LogError($"Running SubOrchestrator");

    // other logic here
}

在此设置中,日志在计时器触发日志之后立即显示“已完成”,但我希望它仅在所有编排(包括子编排)完成后才显示。

azure azure-functions azure-durable-functions azure-functions-isolated
2个回答
0
投票

我对你的代码做了一些修改,它按预期工作了。

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.DurableTask;
using Microsoft.DurableTask.Client;
using Microsoft.Extensions.Logging;
using System.Transactions;

namespace _78332074
{
    public class Function1
    {
        private readonly ILogger<Function1> _logger;

        public Function1(ILogger<Function1> logger)
        {
            _logger = logger;
        }

        [Function("TimerTrigger_EveryMinute")]
        public async Task TimerTrigger_EveryMinute(
        [TimerTrigger("0 * * * * *")] TimerInfo timerInfo,
        [DurableClient] DurableTaskClient starter)
        {
            _logger.LogError($"Running timer trigger");

            string instanceId = await starter.ScheduleNewOrchestrationInstanceAsync("MainOrchestrator", null);
            await starter.WaitForInstanceCompletionAsync(instanceId);

            _logger.LogError($"Completed timer trigger orchestration with ID = '{instanceId}'");
        }

        [Function("MainOrchestrator")]
        public async Task MainOrchestrator(
            [OrchestrationTrigger] TaskOrchestrationContext context)
        {
            _logger.LogError($"Running MainOrchestrator");

            var tasks = new List<Task>();

            tasks.Add(context.CallSubOrchestratorAsync("SubOrchestrator", null));

            await Task.WhenAll(tasks);
        }

        [Function("SubOrchestrator")]
        public async Task SubOrchestrator(
            [OrchestrationTrigger] TaskOrchestrationContext context, TransactionData transaction)
        {
            _logger.LogError($"Running SubOrchestrator");
        }
    }
    public class TransactionData
    {
        public string TransactionId { get; set; }
        public string TransactionType { get; set; }
    }
}

.csproj-

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <AzureFunctionsVersion>v4</AzureFunctionsVersion>
    <OutputType>Exe</OutputType>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <RootNamespace>_78332074</RootNamespace>
  </PropertyGroup>
  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.2.0-rc.1" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.1.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.2.1" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Timer" Version="4.3.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.17.3-preview1" />
    <PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
  </ItemGroup>
  <ItemGroup>
    <None Update="host.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="local.settings.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <CopyToPublishDirectory>Never</CopyToPublishDirectory>
    </None>
  </ItemGroup>
  <ItemGroup>
    <Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext" />
  </ItemGroup>
</Project>

我的输出低于预期。

enter image description here


0
投票

MainOrchestrator 函数似乎被快速连续调用多次,导致我的应用程序出现意外行为。我希望每个计时器触发器仅调用它一次。有人可以帮助我理解为什么会发生这种情况以及如何确保每个计时器触发器仅调用一次 MainOrchestrator 函数吗?

 [Function("TimerTrigger_EveryMinute")]
        public async Task TimerTrigger_EveryMinute(
        [TimerTrigger("0 * * * * *")] TimerInfo timerInfo,
        [DurableClient] DurableTaskClient starter)
        {
            _logger.LogError($"Running timer trigger");
 
            string instanceId = await starter.ScheduleNewOrchestrationInstanceAsync("MainOrchestrator", null);
            await starter.WaitForInstanceCompletionAsync(instanceId);
 
            _logger.LogError($"Completed timer trigger orchestration with ID = '{instanceId}'");
        }
 
        [Function("MainOrchestrator")]
        public async Task MainOrchestrator(
            [OrchestrationTrigger] TaskOrchestrationContext context)
        {
            ILogger log = context.CreateReplaySafeLogger("MainOrchestrator");
            log.LogError("Calling Running MainOrchestrator");
            _logger.LogError($"Running MainOrchestrator");
            var tasks = new List<Task>();
 
            List<TransactionData> transactions = new List<TransactionData>();
 
            log.LogError("before for loop");
            for (var transaction = 0; transaction < 2; transaction++)
            {
                log.LogError("inside for loop");
                tasks.Add(context.CallSubOrchestratorAsync("SubOrchestrator", transaction));
            }
 
            log.LogError("Calling after for loop");
            await Task.WhenAll(tasks);
        }
 
        [Function("SubOrchestrator")]
        public async Task SubOrchestrator(
            [OrchestrationTrigger] TaskOrchestrationContext context, int transaction)
        {
            ILogger log = context.CreateReplaySafeLogger("SubOrchestrator");
            log.LogError("Calling SubOrchestrator");
            _logger.LogError($"Running SubOrchestrator");
        }
 
       
    }
    public class TransactionData
    {
        public string TransactionId { get; set; }
        public string TransactionType { get; set; }
    }

© www.soinside.com 2019 - 2024. All rights reserved.