How to configure scheduled azure webjob to run one instance? - azure

I deployed a continuos Azure WebJob with one function triggered by TimerTrigger with CRON set to run every 2 minutes.
public async void ProcessScheduledNotifications([TimerTrigger("%Api.Settings.Crontab%", RunOnStartup = false, UseMonitor = false)]
TimerInfo timerInfo, TextWriter log)
{
However, my code calls external API and it may take more than 2 minutes to finish. I found that even when one instance is running, the next instance is triggered after 10 minutes.
It there a way to disable this behavior?

TimerTrigger uses the Singleton feature of the WebJobs SDK to ensure that only a single instance of your triggered function is running at any given time.you can use [Singleton] attribute on your functions.The [Singleton] attribute will restrict a function to only run one at a time across all instances, but do be aware that if you're on a Consumption Plan then you'll be charged for the runtime of any instance waiting for another instance to complete, which could significantly increase your costs .
[Singleton]
public async void ProcessScheduledNotifications([TimerTrigger("%Api.Settings.Crontab%", RunOnStartup = false, UseMonitor = false)]
TimerInfo timerInfo, TextWriter log)
{

Related

Azure Function and permanent process

I need to update data from external resource and should do it as often as possible.
I created Azure Function with 1-minute timer and marked it as Singleton:
[Singleton]
[FunctionName("FunctionSync")]
public static void Run([TimerTrigger("0 */1 * * * *")]TimerInfo myTimer, ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
}
but, seems to me, it's being created queue with waiting instances, so it's not good.
Other way - add queue with one message like semaphore and get message on the start add message on the end of function:
[Singleton]
[FunctionName("FunctionSync")]
public async Task Run(
[QueueTrigger("tablet-management-sync-last-datetime", Connection = "StorageConnectionString")]string myQueueItem,
[Queue("tablet-management-sync-last-datetime", Connection = "StorageConnectionString")]CloudQueue outputQueue,
ILogger log
)
{
but this solution is fragile, if something wrong, message is not added to queue and process is stopped.
Which solution is the best?
Azure Functions that are triggered via a TimerTrigger will only be called once per interval, even if there are multiple instances. So this is something that you don't have to worry about. It does this using Blob Leases, and you can read about it here on the webjob sdk wiki.

Manually trigger time based Azure Functions on dev [duplicate]

This question already has answers here:
What is the simplest way to run a timer-triggered Azure Function locally once?
(9 answers)
Closed 1 year ago.
My task runs once a day when deployed. For development currently I just changed the CRON to "every minute" and wait for that minute to hit in order for the function to be triggered for me to do the debugging. Is there a way such that I can leave my timer code to stay as "Every day" but still be able to kick it off manually.
In Azure I can just go to the function resource and click "Run" that will start it regardless of the timer. I am looking for something similar on my dev.
You are probably looking for this on the Timer Trigger attribute,
[TimerTrigger("", RunOnStartup = true)]TimerInfo timer
That should kick it off on startup.
It doesn't look like there is a direct solution available to manually (or even through and http request) trigger a time based Azure function.
Possible Workaround
Have a second http triggered function that has the same logic/code. You can use this 2nd function for testing on demand basis.
Please see the discussion in these 2 threads, it's very relevant to you -
Any method for testing timer trigger function
Time triggered azure function to trigger immediately after deploy
As #neo99 mentioned, simple answer is it is not possible just out of the box. The reason is input parameters for Run method of Trigger function are different for different type of triggers.
For e.g. you are looking to manually trigger(HttpTrigger) a TimerTrigger
Timer Trigger:
[FunctionName("TimerTriggerCSharp")]
public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, TraceWriter log)
Http Trigger:
[FunctionName("HttpTriggerCSharp")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req,
TraceWriter log)

Azure WebJobs Scheduler

Can we have multiple Schedules in a Single web Job of Microsoft Azure.
We have certain functionalities to happen in a single job within particular time
i.e multiple schedules so we have tried through the timer but i need to know is there any other option.Thank you
You can use the TimerTriggerAttribute: Please refer https://github.com/Azure/azure-webjobs-sdk-extensions#timertrigger
// Triggered every hours
public static void HourlyTimerJob([TimerTrigger("00:01:00")] TimerInfo timerInfo, TextWriter log)
{
log.WriteLine("Your first scheduled job!");
}
// Triggered every 15 minutes
public static void MinutelyTimerJob([TimerTrigger("00:00:15")] TimerInfo timerInfo, TextWriter log)
{
log.WriteLine("Your second scheduled job!");
}
You can always use CRON expression for web jobs to e.g., let it run at particular times. You can refer to this official doc.

WebJob QueueTrigger - limit per function

I've got a few Webjobs in place, each of which respond to a number of QueueTrigger, e.g.
public static void ProcessMessage([QueueTrigger("XXXXXXX")] string message, TextWriter log)
{
//processing message
}
public static void ProcessMessage([QueueTrigger("YYYYYY")] string message, TextWriter log)
{
//processing message
}
Should I be separating out each trigger to a separate job? Are there any reasons why continuing on this path is a bad idea, i.e. the more queues it can trigger the less functions get executed due to thread limits?
What you are doing is the common approach - the WebJobs SDK JobHost is designed to handle many different job functions all within the same application. It is true that all the job functions within a single host will share the same process/memory space and limits, but for most scenarios this isn't a problem and is the recommended approach.
For QueueTrigger specifically, each of your functions will efficiently poll for new work, and when work is available each will pull messages in batches of 16 (configurable via JobHostConfiguration.Queues) and process them in parallel.
You can also scale out if needed by increasing the number of instances your WebJob runs on. Each instance will then work cooperatively with the others to handle more load.

Azure WebJob won't run locally in debugger

My Azure WebJob used to run in the VS2015 Debugger, but I found it gradually became very intermittent and now won't run at all. It works fine it I deploy it to Azure. The job is marked as RunOnStartUp.
public class Program
{
static void Main()
{
var config = new JobHostConfiguration();
config.UseTimers();
var host = new JobHost(config);
host.RunAndBlock();
}
}
public class TestJob : BaseJob
{
public static async Task StartupJob([TimerTrigger("05:00:00", RunOnStartup = true)] TimerInfo timerInfo, TextWriter log)
{
log.WriteLine("StartupJob");
await Jobs.Test(some params);
log.WriteLine("Sorted");
}
}
What do I need to do to get it running in the Debugger?
I'm guessing you use the same storage account for your job in Azure and when you debug it locally? If that's the case - the TimeTrigger runs as a singleton which means it needs to acquire a lock to be able to execute. If your webjob is already running in Azure your local version, which you're trying to debug, is not able to acquire the lock.
To avoid this just use different storage accounts for "live" Azure version and local local development.
I would also recommend to enable "development settings" - config.UseDevelopmentSettings(); - when you debug locally. If you enable it you'll see the messages "unable to acquire lock for function..." (or something similar).
See Jason Haley's comment in this thread:
(total hack but should work) rename the function while debugging so
the lock listener blob name will be different.
This hack worked for me. Maybe to make it less hacky, you could use the Disable-attribute to create a timer-triggered function that would only be enabled in your local environment:
Create "MyFunction", which handles the logic. This is the one that will run in your Azure app. Note RunOnStartup=false as recommended by the docs.
[FunctionName("MyFunction")]
public async Task RunJob(
[TimerTrigger("0 0 0 * * *", RunOnStartup = false)] TimerInfo timer)
{
//logic here
}
Create "MyFunction-Local" with the Disable attribute and a different method name. All this does is call the method above.
[FunctionName("MyFunction-Local")]
[Disable("Disable_MyFunction")]
public async Task RunJobLocal(
[TimerTrigger("0 0 0 * * *", RunOnStartup = true)] TimerInfo timer)
{
RunJob(timer);
}
In your local app configuration, set {"Disable_MyFunction" = false}, whereas for the app running in Azure, set this to true.

Resources