Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LastFailure.ErrorType is System.AggregateException when calling async activity with retry handler #155

Closed
savbace opened this issue Jun 13, 2023 · 2 comments

Comments

@savbace
Copy link

savbace commented Jun 13, 2023

Preconditions

  • Call activity which returns Task (async) with custom retry handler using TaskOptions.FromRetryHandler.
  • The activity throws ApplicationException.
  • Use LastFailure.IsCausedBy<ApplicationException>() to check whether need to retry.

Expected result: LastFailure.IsCausedBy<ApplicationException>() returns true;
Actual result: LastFailure.IsCausedBy<ApplicationException>() returns false;

Sample code

public class BackgroundOrchestrationFuncs
{
  [Function(nameof(BackgroundOrchestration))]
  public async Task BackgroundOrchestration([OrchestrationTrigger] TaskOrchestrationContext context)
  {
    var input = context.GetInput<BackgroundOptions>();
    TaskOptions options = TaskOptions.FromRetryHandler(context =>
    {
      if (!context.LastFailure.IsCausedBy<ApplicationException>()) // get false here
      {
        return false;
      }

      return context.LastAttemptNumber < 3;
    });

    await context.CallActivityAsync(nameof(RiskyActivity), input, options);
  }

  [Function(nameof(RiskyActivity))]
  public async Task RiskyActivity([ActivityTrigger] BackgroundOptions options)
  {
    await Task.Delay(3000);
    throw new ApplicationException("Failed to run!");
  }
}

Details
LastFailure contains information about System.AggregateException instead of ApplicationException when activity function is asynchronous.
From the other side if activity function is synchronous then LastFailure contains expected information about ApplicationException.
Repo for reproducing the issue: DurableRetryPlayground
Here is a value of LastFailure during debug session from the repo:

LastFailure	{System.AggregateException: One or more errors occurred. (Failed to run!)}	Microsoft.DurableTask.TaskFailureDetails
	EqualityContract	{Name = "TaskFailureDetails" FullName = "Microsoft.DurableTask.TaskFailureDetails"}	System.Type {System.RuntimeType}
	ErrorMessage	"One or more errors occurred. (Failed to run!)"	string
	ErrorType	"System.AggregateException"	string
	InnerFailure	null	Microsoft.DurableTask.TaskFailureDetails
	StackTrace	"   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)\r\n   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)\r\n   at System.Threading.Tasks.Task`1.get_Result()\r\n   at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionInvoker`2.<>c.<InvokeAsync>b__6_0(Task`1 t) in D:\\a\\_work\\1\\s\\src\\DotNetWorker.Core\\Invocation\\DefaultFunctionInvoker.cs:line 32\r\n   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()\r\n   at System.Threading.Tasks.Task.<>c.<.cctor>b__272_0(Object obj)\r\n   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)\r\n--- End of stack trace from previous location ---\r\n   at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)\r\n--- End of stack trace from previous location ---\r\n   at Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor.ExecuteAsync(FunctionContext context) in D:\\a\\_work\\1\\s\\src\\DotNetWorker.Core\\Invocation\\DefaultFunctionExecutor.cs:line 45\r\n   at Microsoft.Azure.Functions.Worker.OutputBindings.OutputBindingsMiddleware.Invoke(FunctionContext context, FunctionExecutionDelegate next) in D:\\a\\_work\\1\\s\\src\\DotNetWorker.Core\\OutputBindings\\OutputBindingsMiddleware.cs:line 13\r\n   at Microsoft.Azure.Functions.Worker.Extensions.DurableTask.DurableTaskFunctionsMiddleware.Invoke(FunctionContext functionContext, FunctionExecutionDelegate next) in /_/src/Worker.Extensions.DurableTask/DurableTaskFunctionsMiddleware.cs:line 22\r\n   at Microsoft.Azure.Functions.Worker.FunctionsApplication.InvokeFunctionAsync(FunctionContext context) in D:\\a\\_work\\1\\s\\src\\DotNetWorker.Core\\FunctionsApplication.cs:line 77\r\n   at Microsoft.Azure.Functions.Worker.Handlers.InvocationHandler.InvokeAsync(InvocationRequest request) in D:\\a\\_work\\1\\s\\src\\DotNetWorker.Grpc\\Handlers\\InvocationHandler.cs:line 88"	string

Could you please clarify whether my expectations are correct?

@jviau
Copy link
Member

jviau commented Jun 14, 2023

This is a behavior of the functions dotnet worker: Azure/azure-functions-dotnet-worker#993

@savbace
Copy link
Author

savbace commented Jun 19, 2023

@jviau oh, I see. Thanks for pointing out the original issue! Closing this ticket then.

@savbace savbace closed this as not planned Won't fix, can't repro, duplicate, stale Jun 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants