.NET 8 持久功能 - 在 VS 2022 中本地运行时无法捕获活动超时

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

我目前正在开发一个持久功能来处理大文件上传,并且在尝试本地测试活动超时时遇到一些问题。

简而言之,我尝试测试的场景如下:orchestrator 将处理上传所需的信息传递给某个活动 (

ResumeUpload
),并且该活动的
CallActivityAsync
任务是否因以下原因导致
TaskFailedException
失败?超时,然后我就会知道上传尚未完成,我应该再次调用它来恢复上传。

为了实现此目的,我在我的

"functionTimeout": "00:01:00"
中设置了
host.json
,并使用
ResumeUpload
Task.Delay()
更改为无限期等待。 在发生超时之前,这一切正常,此时我希望 VS 在协调器捕获
TaskFailedException
的断点处停止;相反,
dotnet.exe
会死掉并且调试会话结束。

编排器和活动(简化):

[Function(nameof(RunOrchestrator))]
public static async Task RunOrchestrator([OrchestrationTrigger] TaskOrchestrationContext context)
{
    var logger = context.CreateReplaySafeLogger(context.Name);
    var uploadRequest = context.GetInput<UploadRequest>();

    try
    {
        await context.CallActivityAsync(nameof(ResumeUpload), uploadRequest);
    }
    catch (TaskFailedException ex)
    {
        // This is never reached!
        logger.LogError(ex, "inspect task failure exception");
    }
}

[Function(nameof(ResumeUpload))]
public static async Task ResumeUpload([ActivityTrigger] UploadRequest uploadRequest, FunctionContext context)
{
    // Force this activity to time out
    await Task.Delay(TimeSpan.FromHours(1)); 
}

发生超时时,我在运行项目时 VS 生成的终端中看到一条消息,到目前为止一切顺利:

[2024-11-06T17:10:06.427Z] Microsoft.Azure.WebJobs.Host: Timeout value of 00:01:00 was exceeded by function: Functions.ResumeUpload.
[2024-11-06T17:10:08.451Z] A function timeout has occurred. Restarting worker process executing invocationId '9d808fd3-6274-4211-9dcf-d514e8fe3ec2'.

然而,该进程随后立即终止,并且我被转回 VS,而没有到达我在协调器的

catch
语句中放置的断点。如果我尝试捕获通用
Exception
而不是
TaskFailedException
,情况也是如此。

VS runner window

我已经在 Google 上搜索了几个小时,但没有遇到任何人报告此问题,并且在我的搜索中,我遇到了几个示例,这些示例表明我正在尝试做的事情应该是可能的,例如:

我对 Azure Functions 非常陌生,所以我可能会遗漏一些明显的东西,感谢您能想到的任何帮助或提示!预先感谢。

编辑:

我将该函数部署到 Azure,当活动超时时,编排器确实捕获了

TaskFailedException
,因此这看起来像是我的机器/VS/Azure 模拟器的问题。

c# azure-functions visual-studio-2022 .net-8.0 azure-durable-functions
1个回答
0
投票

我可以通过用 try-catch 块封装活动函数来运行您的代码,并且能够命中 Orchestrator 函数的 catch 块中的异常。

修改示例代码:

public static class Function1
{
    [Function(nameof(Function1))]
    public static async Task RunOrchestrator([OrchestrationTrigger] TaskOrchestrationContext context)
    {
        var logger = context.CreateReplaySafeLogger(context.Name);
        var uploadRequest = context.GetInput<UploadRequest>();

        try
        {
            await context.CallActivityAsync(nameof(ResumeUpload), uploadRequest);
        }
        catch (TaskFailedException ex)
        {
            logger.LogError(ex, "inspect task failure exception");
        }
    }

    [Function(nameof(ResumeUpload))]
    public static async Task ResumeUpload([ActivityTrigger] UploadRequest uploadRequest, FunctionContext context,ILogger logger)
    {
      
        try
        {
            await Task.Delay(TimeSpan.FromHours(1));
        }
        catch (TaskFailedException ex)
        {
            logger.LogError("inspect activity task failure exceptions");
        }
    }

    [Function("Function1_HttpStart")]
    public static async Task<HttpResponseData> UploadRequest(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req,
        [DurableClient] DurableTaskClient client,
        FunctionContext executionContext)
    {
        ILogger logger = executionContext.GetLogger("Function1_HttpStart");

        string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(
            nameof(Function1));

        logger.LogInformation("Started orchestration with ID = '{instanceId}'.", instanceId);
        return await client.CreateCheckStatusResponseAsync(req, instanceId);
    }

能够在异常catch块处命断点。

enter image description here

enter image description here

输出:

enter image description here


Functions:

        Function1_HttpStart: [GET,POST] http://localhost:7070/api/Function1_HttpStart

        Function1: orchestrationTrigger

        ResumeUpload: activityTrigger

For detailed output, run func with --verbose flag.
[2024-11-07T07:17:44.908Z] Executing 'Functions.Function1' (Reason='(null)', Id=53e3689e-e412-4ac5-ac5a-2f48651e7c4a)
[2024-11-07T07:17:49.162Z] Host lock lease acquired by instance ID '000000000000000000000000F72731CC'.
[2024-11-07T07:18:05.470Z] inspect task failure exception
[2024-11-07T07:18:05.471Z] Result: inspect task failure exception
Exception: Microsoft.DurableTask.TaskFailedException: Task 'ResumeUpload' (#0) failed with an unhandled exception: Exception while executing function: Functions.ResumeUpload
[2024-11-07T07:18:05.473Z]  ---> DurableTask.Core.Exceptions.TaskFailedException: Exception of type 'DurableTask.Core.Exceptions.TaskFailedException' was thrown.
[2024-11-07T07:18:05.475Z]    at DurableTask.Core.TaskOrchestrationContext.ScheduleTaskInternal(String name, String version, String taskList, Type resultType, Object[] parameters) in /_/src/DurableTask.Core/TaskOrchestrationContext.cs:line 121
[2024-11-07T07:18:05.477Z]    at DurableTask.Core.TaskOrchestrationContext.ScheduleTaskToWorker[TResult](String name, String version, String taskList, Object[] parameters) in /_/src/DurableTask.Core/TaskOrchestrationContext.cs:line 92
[2024-11-07T07:18:05.478Z]    at DurableTask.Core.TaskOrchestrationContext.ScheduleTask[TResult](String name, String version, Object[] parameters) in /_/src/DurableTask.Core/TaskOrchestrationContext.cs:line 84
[2024-11-07T07:18:05.480Z]    at Microsoft.DurableTask.Worker.Shims.TaskOrchestrationContextWrapper.CallActivityAsync[T](TaskName name, Object input, TaskOptions options)
[2024-11-07T07:18:05.481Z]    --- End of inner exception stack trace ---
[2024-11-07T07:18:05.483Z]    at Microsoft.DurableTask.Worker.Shims.TaskOrchestrationContextWrapper.CallActivityAsync[T](TaskName name, Object input, TaskOptions options)
[2024-11-07T07:18:05.484Z]    at FunctionApp1.Function1.RunOrchestrator(TaskOrchestrationContext context) in C:\Users\uname\Source\Repos\FunctionApp1\FunctionApp1\Function1.cs:line 19
Stack:    at Microsoft.DurableTask.Worker.Shims.TaskOrchestrationContextWrapper.CallActivityAsync[T](TaskName name, Object input, TaskOptions options)
[2024-11-07T07:18:05.488Z]    at FunctionApp1.Function1.RunOrchestrator(TaskOrchestrationContext context) in C:\Users\uname\Source\Repos\FunctionApp1\FunctionApp1\Function1.cs:line 19.
[2024-11-07T07:18:11.197Z] Executing 'Functions.Function1' (Reason='(null)', Id=3797fe6c-3f4c-4561-b9e5-5093c44bea9d)
[2024-11-07T07:18:24.414Z] inspect task failure exception
[2024-11-07T07:18:24.416Z] Result: inspect task failure exception
Exception: Microsoft.DurableTask.TaskFailedException: Task 'ResumeUpload' (#0) failed with an unhandled exception: Exception while executing function: Functions.ResumeUpload
[2024-11-07T07:18:24.419Z]  ---> DurableTask.Core.Exceptions.TaskFailedException: Exception of type 'DurableTask.Core.Exceptions.TaskFailedException' was thrown.
[2024-11-07T07:18:24.421Z]    at DurableTask.Core.TaskOrchestrationContext.ScheduleTaskInternal(String name, String version, String taskList, Type resultType, Object[] parameters) in /_/src/DurableTask.Core/TaskOrchestrationContext.cs:line 121
[2024-11-07T07:18:24.423Z]    at DurableTask.Core.TaskOrchestrationContext.ScheduleTaskToWorker[TResult](String name, String version, String taskList, Object[] parameters) in /_/src/DurableTask.Core/TaskOrchestrationContext.cs:line 92
[2024-11-07T07:18:24.425Z]    at DurableTask.Core.TaskOrchestrationContext.ScheduleTask[TResult](String name, String version, Object[] parameters) in /_/src/DurableTask.Core/TaskOrchestrationContext.cs:line 84
[2024-11-07T07:18:24.427Z]    at Microsoft.DurableTask.Worker.Shims.TaskOrchestrationContextWrapper.CallActivityAsync[T](TaskName name, Object input, TaskOptions options)
[2024-11-07T07:18:24.429Z]    --- End of inner exception stack trace ---
[2024-11-07T07:18:24.432Z]    at Microsoft.DurableTask.Worker.Shims.TaskOrchestrationContextWrapper.CallActivityAsync[T](TaskName name, Object input, TaskOptions options)
[2024-11-07T07:18:24.434Z]    at FunctionApp1.Function1.RunOrchestrator(TaskOrchestrationContext context) in C:\Users\uname\Source\Repos\FunctionApp1\FunctionApp1\Function1.cs:line 19
Stack:    at Microsoft.DurableTask.Worker.Shims.TaskOrchestrationContextWrapper.CallActivityAsync[T](TaskName name, Object input, TaskOptions options)
[2024-11-07T07:18:24.436Z]    at FunctionApp1.Function1.RunOrchestrator(TaskOrchestrationContext context) in C:\Users\uname\Source\Repos\FunctionApp1\FunctionApp1\Function1.cs:line 19.
[2024-11-07T07:18:44.910Z] Timeout value of 00:01:00 exceeded by function 'Functions.Function1' (Id: '53e3689e-e412-4ac5-ac5a-2f48651e7c4a'). Initiating cancellation.
[2024-11-07T07:18:44.952Z] Executed 'Functions.Function1' (Failed, Id=53e3689e-e412-4ac5-ac5a-2f48651e7c4a, Duration=60078ms)
[2024-11-07T07:18:44.953Z] Microsoft.Azure.WebJobs.Host: Timeout value of 00:01:00 was exceeded by function: Functions.Function1.
[2024-11-07T07:18:46.988Z] A function timeout has occurred. Restarting worker process executing invocationId '53e3689e-e412-4ac5-ac5a-2f48651e7c4a'.
[2024-11-07T07:18:47.270Z] Azure Functions .NET Worker (PID: 3888) initialized in debug mode. Waiting for debugger to attach...
[2024-11-07T07:18:50.624Z] Executed 'Functions.Function1' (Succeeded, Id=3797fe6c-3f4c-4561-b9e5-5093c44bea9d, Duration=39430ms)
© www.soinside.com 2019 - 2024. All rights reserved.