1

I recently upgraded to the isolated NET7 Azure Functions worker. Durable Function's API has changed quiete a bit in with that, but it is GA now.

I need to get the orchestration's instance id from within the activity function. Previously (with the in-process model), I was able to inject the IDurableActivityContext interface in the function and reference the instance id from there.

Afaik, the equivalent now is the TaskActivityContext class. However, if I inject this into the function it is always null.

How to get it? I could just pass it as an input from the orchestrator. But I would not prefer this.

namespace MyNamespace;

public class TestActionable
{
    private readonly ILogger _log;
    public TestActionable(ILogger<TestActionable> log) => _log = log;

    [Function("TestActionable_Trigger")]
    public async Task TriggerWorkflow([DurableClient] DurableTaskClient client,
    [QueueTrigger(QueueNames.ACTIONABLE_TEST, Connection = BindingConnectionNames.MY_BINDINGNAME)]string q)
    {
        var now = DateTimeOffset.UtcNow.ToIsoString();
        _log.LogWarning("Triggering workflow now");
        await client.ScheduleNewOrchestrationInstanceAsync("TestActionable_Workflow", input: now);
        _log.LogWarning("Triggered");
    }


    [Function("TestActionable_Workflow")]
    public static async Task RunWorkflow([OrchestrationTrigger] TaskOrchestrationContext ctx)
    {
        var log = ctx.CreateReplaySafeLogger("TestActionable_Workflow");
        log.LogWarning("Workflow started with input= {input}", ctx.GetInput<string>());

        var input = new { a=1337 };
        var output = await ctx.CallActivityAsync<bool>("TestActionable_Activity", input);
        log.LogWarning("Activity completed successfully= {output}", output);
        log.LogWarning("Workflow complete");
    }
    

    [Function("TestActionable_Activity")]
    public async Task<bool> RunActivity([ActivityTrigger] object input, TaskActivityContext ctx)
    {
        _log.LogWarning("Started activity, input= {i}", input);

        if (ctx is null)
        {
            _log.LogError("TaskActivityContext is null");
            return false;
        }

        _log.LogWarning("TaskActivityContext= {ctx}", ctx.Serialize());
        _log.LogWarning("The orchestration's instance id is= {ctx}", ctx.InstanceId);
        _log.LogWarning("Waited 1s, activity complete");
        await Task.Delay(1000);
        return true;
    }
}

Here's the log output

[2023-03-03T08:03:01.668Z] Executing 'Functions.TestActionable_Trigger' (Reason='New queue message detected on 'actionable-test'.', Id=1cc9891b-85a4-4dd4-90e2-19417cc7519a)
[2023-03-03T08:03:01.674Z] Trigger Details: MessageId: ae725935-4b5c-4299-ac48-44f1af934363, DequeueCount: 1, InsertedOn: 2023-03-03T08:03:00.000+00:00
[2023-03-03T08:03:01.863Z] Host lock lease acquired by instance ID '00000000000000000000000041F3D3B5'.
[2023-03-03T08:03:02.192Z] Scheduling new TestActionable_Workflow orchestration with instance ID '388c8c6c4f554f49ac1d9f50ac747e9b' and 28 bytes of input data.
[2023-03-03T08:03:02.192Z] Triggering workflow now
[2023-03-03T08:03:02.648Z] Triggered
[2023-03-03T08:03:02.757Z] Executed 'Functions.TestActionable_Trigger' (Succeeded, Id=1cc9891b-85a4-4dd4-90e2-19417cc7519a, Duration=1152ms)
[2023-03-03T08:03:06.020Z] Executing 'Functions.TestActionable_Workflow' (Reason='(null)', Id=0e4c510b-78c9-4e3a-8e9a-8f3cef8b4eb5)
[2023-03-03T08:03:06.213Z] Workflow started with input= 2023-03-03T08:03:02.12594Z
[2023-03-03T08:03:06.333Z] Executed 'Functions.TestActionable_Workflow' (Succeeded, Id=0e4c510b-78c9-4e3a-8e9a-8f3cef8b4eb5, Duration=358ms)
[2023-03-03T08:03:06.498Z] Executing 'Functions.TestActionable_Activity' (Reason='(null)', Id=07db96ca-df51-41e2-9906-e7012d7f2eda)
[2023-03-03T08:03:06.533Z] Started activity, input= {"a":1337}
[2023-03-03T08:03:06.533Z] TaskActivityContext is null
[2023-03-03T08:03:06.548Z] Executed 'Functions.TestActionable_Activity' (Succeeded, Id=07db96ca-df51-41e2-9906-e7012d7f2eda, Duration=56ms)
[2023-03-03T08:03:06.692Z] Executing 'Functions.TestActionable_Workflow' (Reason='(null)', Id=edde658a-c820-41bb-8d09-cc13ca14040d)
[2023-03-03T08:03:06.721Z] Activity completed successfully= False
[2023-03-03T08:03:06.721Z] Workflow complete
[2023-03-03T08:03:06.739Z] Executed 'Functions.TestActionable_Workflow' (Succeeded, Id=edde658a-c820-41bb-8d09-cc13ca14040d, Duration=52ms)
baouss
  • 1,312
  • 1
  • 22
  • 52

2 Answers2

1

Apparently, this is by design. As noted here there is no equivalent in the isolated worker for DurableActivityContext. The TaskActivityContext I mentioned in my question, and which I figured to be the replacement for what I need (which it is not), appears to be only usable with the new approach of writing durable functions code, see class-based.

baouss
  • 1,312
  • 1
  • 22
  • 52
0

To revive this, although there's no equivalent of IDurableActivityContext, there's still a way to get the instance ID of the orchestration. Add a string parameter to the activity function with the name "instanceId," and it will receive the instance ID.

If the activity function already has an input parameter, that one should be the one with the [ActivityTrigger] attribute. In that case, you don't need any attribute on the "instanceId" parameter.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129