How can I start a Azure Function at a specific time?

Viewed 1368

I have a simple C# console app that will GET data from one API and POST to another. I plan to use Azure Functions (or a Webjob). A part of the GET data is the time when the next execution of the app needs to be. So in the C# app code I need to create some kind of trigger that will execute the same app/function at the given time. How can this be done in Azure?

3 Answers

Simple but not really clean:

Use http triggered azure function and execute post request passing execution date as parameter. Than inside use a task scheduling lib like quartz to execute it in given time.

http function and how to read params: https://docs.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook-trigger?tabs=csharp

Quartz: https://www.quartz-scheduler.net/

More advanced:

Use azure queue to push your message in given time. Than your receiver can execute it immediately, as its queue that is making sure time intervals are respected. More about that:

https://docs.microsoft.com/en-us/azure/service-bus-messaging/message-sequencing

You can use a DurableFunction, in which you pass your desired scheduled-datetime. The DurableFunction can be called from any normal azure function (e.g. HttpTrigger-Function). To achieve the functionality, the DurableFunction uses CreateTimer, which waits, until the DateTime is reached.

It is made up of three parts

  1. A DurableFunction (orchestration)
  2. An Activity, which is called from the DurableFunction
  3. A normal HttpTrigger-Function which calls the DurableFunction and passes the desired ScheduleTime to the DurableFunction

Here the full code, which you can use by calling the normal Azure Function. In my case it is http://localhost:7071/api/RaiseScheduledEvent_HttpStart. To have the sample running in VisualStudio, please make sure you have the following setting in your local.settings.json:

"AzureWebJobsStorage": "UseDevelopmentStorage=true",

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;

namespace api
{
    public class RaiseEventParameter
    {
        public DateTime RaiseAt { get; set; }
    }

    public static class RaiseScheduledEvent
    {
        // This is the DurableFunction, which takes the ScheduledTime (RaiseAt) as parameter
        [FunctionName("RaiseScheduledEvent")]
        public static async Task RunOrchestrator(
            [OrchestrationTrigger] IDurableOrchestrationContext context)
        {
            var raiseAt = context.GetInput<RaiseEventParameter>().RaiseAt;

            await context.CreateTimer(raiseAt, CancellationToken.None);

            await context.CallActivityAsync("RaiseScheduledEvent_TimerElapsed", null);
        }

        // When the timer elapsed, the below activity is called.
        // Here you can do, whatever you planned at the scheduled-time
        [FunctionName("RaiseScheduledEvent_TimerElapsed")]
        public static void TimerElapsed([ActivityTrigger] object input, ILogger log)
        {
            Console.WriteLine("Elapsed at " + DateTime.UtcNow.ToString());
        }

        // This is the normal Http-Trigger function, which calls the durable function
        // Instead of hardcoding the RaiseAt, you could use any input of your Azure Function
        [FunctionName("RaiseScheduledEvent_HttpStart")]
        public static async Task<HttpResponseMessage> HttpStart(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req,
            [DurableClient] IDurableOrchestrationClient starter,
            ILogger log)
        {
            var parameter = new RaiseEventParameter()
            {
                RaiseAt = DateTime.UtcNow.AddSeconds(5)
            };

            string instanceId = await starter.StartNewAsync("RaiseScheduledEvent", parameter);

            return starter.CreateCheckStatusResponse(req, instanceId);
        }
    }
}
Related