Azure/azure-functions-durable-extension

Calling Class based Activity function via Generators not working

nvhoanganh opened this issue · 3 comments

Description

A clear and concise description of what the bug is. Please make an effort to fill in all the sections below; the information will help us investigate your issue.

I created a very simple Durable function in isolated mode and tried the Class based activity function. I can see that activity function is generated in the list of registered functions and I can see the function is being triggered but my code was not running.

Here is the minimum repo https://github.com/nvhoanganh/AzureFuncDurableDotNet8/blob/main/TestDurableFunction.cs

NOTE: JavaScript issues should be reported here: https://github.com/Azure/azure-functions-durable-js

Expected behavior

A clear and concise description of what you expected to happen.
My code in the class based activity function should be executed

Actual behavior

A clear and concise description of what actually happened.
It looks like it is executed but it is not

Relevant source code snippets

// insert code snippet here
[DurableTask(nameof(SayHelloClass))]
    public class SayHelloClass : TaskActivity<string, string>
    {
        private readonly ILogger<SayHelloClass> logger;

        public SayHelloClass(ILogger<SayHelloClass> logger)
        {
            this.logger = logger;
        }

        public override async Task<string> RunAsync(TaskActivityContext context, string input)
        {
            logger.LogInformation($"Saying {input} back");
            await Task.Delay(200);
            return $"Hello {input} via Class!";
        }
    }


    public static class TestDurableFunction
    {
        [Function(nameof(TestDurableFunction))]
        public static async Task<List<string>> RunOrchestrator(
            [OrchestrationTrigger] TaskOrchestrationContext context)
        {
            ILogger logger = context.CreateReplaySafeLogger(nameof(TestDurableFunction));
            logger.LogInformation("Saying hello.");
            var outputs = new List<string>();

            // Replace name and input with values relevant for your Durable Functions Activity
            outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Tokyo"));
            outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Seattle"));
            outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "London"));

            // this shown as executed in the console but the activity function is not executed
            outputs.Add(await context.CallActivityAsync<string>(nameof(SayHelloClass), "There"));
            // this shown as executed in the console but the activity function is not executed
            outputs.Add(await context.CallSayHelloClassAsync("Blah"));

            // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
            return outputs;
        }

        [Function(nameof(SayHello))]
        public static string SayHello([ActivityTrigger] string name, FunctionContext executionContext)
        {
            ILogger logger = executionContext.GetLogger("SayHello");
            logger.LogInformation("Saying hello to {name}.", name);
            return $"Hello {name}!";
        }

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

            // Function input comes from the request content.
            string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(
                nameof(TestDurableFunction));

            logger.LogInformation("Started orchestration with ID = '{instanceId}'.", instanceId);

            // Returns an HTTP 202 response with an instance management payload.
            // See https://learn.microsoft.com/azure/azure-functions/durable/durable-functions-http-api#start-orchestration
            return await client.CreateCheckStatusResponseAsync(req, instanceId);
        }
    }

Known workarounds

Provide a description of any known workarounds you used.

App Details

  • Durable Functions extension version (e.g. v1.8.3): 1.1.1
  • Azure Functions runtime version (1.0 or 2.0): 2.0
  • Programming language used: csharp - .NET 8

Screenshots

If applicable, add screenshots to help explain your problem.
image

If deployed to Azure

We have access to a lot of telemetry that can help with investigations. Please provide as much of the following information as you can to help us investigate!

  • Timeframe issue observed:
  • Function App name:
  • Function name(s):
  • Azure region:
  • Orchestration instance ID(s):
  • Azure storage account name:

If you don't want to share your Function App or storage account name GitHub, please at least share the orchestration instance ID. Otherwise it's extremely difficult to look up information.

Hi @nvhoanganh thanks for reporting this. Does your orchestration work correctly (including the type-safe invocation at the end) if you define the activity as a normal function instead of a class? I want to confirm whether that source-generator pattern is working or if it's also being affected.

Hi @cgillum , if I define it using normal function it works fine

Thanks for this info. We’ll take a look into why the class-based syntax is no longer working with the source generated extension methods.