I have a continuous webjob that contains a function with a TimerTrigger configured to run each minute:
public static async Task TestFunction([TimerTrigger("0 * * * * *")] TimerInfo info)
{
Console.WriteLine($"{DateTime.UtcNow:s}: beginning to process the function...");
// Imitate a long processing
await Task.Delay(75 * 1000);
Console.WriteLine($"{DateTime.UtcNow:s}: finished processing the function");
}
Let's say the first invocation is at 00:00:00. Then, because the function runs longer than a minute, the next invocation is past due and is triggered at 00:01:15. The next is at 00:02:30 etc.
I'd like the function to be invoked exactly on schedule, even if it'll result in two functions running in parallel.
Multiple instances section in WebJobs SDK docs states that:
"The timer trigger automatically ensures that only one instance of the timer runs, so you don't get more than one function instance running at a given scheduled time"
Is there any way to change this behaviour?
Or should I use something else to achieve the required behaviour? (Scheduled WebJob, Azure Function or some other service?)
I've solved the problem by introducing a queue and splitting the function into two: a producer and a consumer.
The first function is triggered on schedule and just puts messages on to the queue:
public static async Task TestProducer([TimerTrigger("0 * * * * *")] TimerInfo info)
{
var startTime = DateTime.UtcNow;
var message = new BrokeredMessage(startTime);
var queueClient = QueueClient.CreateFromConnectionString("ServiceBusConnString", "queue-name");
await queueClient.SendAsync(message);
}
The second function does the actual work:
public static async Task TestConsumer([ServiceBusTrigger("queue-name")] DateTime startTime)
{
Console.WriteLine($"{DateTime.UtcNow:s}: beginning to process the function for startTime={startTime}");
// Imitate a long processing that depends on a startTime
await Task.Delay(75 * 1000);
Console.WriteLine($"{DateTime.UtcNow:s}: finished processing the function for startTime={startTime}");
}
When the first function enqueues a new message while the second function is still working, a new instance of the second function is invoked.