Wednesday, September 23, 2020

Azure Durable Functions for Monitoring

In this post, let's see how Azure Durable Functions can be used to Monitor a long-running task. It's actually pretty easy. But there are some important things to Note.

Consider the below code. This is a basic implementation of such a monitoring functionality using an Orchestration Function. Here basically we are triggering an Activity function that will invoke a long-running task (here it is returning the taskId so we can poll for status using that). And then we are polling every 15 seconds for 60 seconds by triggering another Activity Function. If we are able to get a successful result within that time frame, we are returning that, else we throw a TimeoutException or you can do whatever you want.

[FunctionName("MonitorTask")]
public static async Task<TaskResult> Run([OrchestrationTriggerIDurableOrchestrationContext context)
{
    TaskInput taskInput = context.GetInput<TaskInput>();

    ProcessingResult processingResult = await context.CallActivityAsync<ProcessingResult>("InvokeLongRunningTask", taskInput);

    var pollingIntervalInSeconds = 15;
    DateTime expiryTime = context.CurrentUtcDateTime.AddSeconds(60);

    while (context.CurrentUtcDateTime < expiryTime)
    {
        TaskResult taskResult = await context.CallActivityAsync<TaskResult>("GetTaskResult", processingResult.TaskId);

        if (taskResult.Status == "Success")
        {
            return taskResult;
        }

        // Orchestration sleeps until this time.
        DateTime nextCheck = context.CurrentUtcDateTime.AddSeconds(pollingIntervalInSeconds);
        await context.CreateTimer(nextCheck, CancellationToken.None);
    }

    throw new TimeoutException("Timeout Occurred");
}

The most important thing here is, we are getting CurrentUtcDateTime from the IDurableOrchestrationContext. The reason for that is, Durable Functions should be deterministic. It should be deterministic because Durable Functions use Event Sourcing pattern to determine it's current state (and that is rather than keeping the current state, it tracks how/what events made the function to get into the current state). If we use DateTime.UtcDateTime, for every time it replays the message, the DateTime will be different and will end up with a infinite wait. CurrentUtcDateTime will be the same for every replay of this specific instance.

So hope this helps!

Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment