In my dev environment, I have an Azure Functions with 21 functions and the app plan is consumption.
Some functions have a timer trigger and at the end of the process each function sends an email. I have 2 type of timer trigger:
run a function every 20 minutes
run a function once at a particular time in the night
Every 20 minutes the function is doing what I expect. Great.
The problem I'm facing is with the function that they have to start at a particular time. Basically, they don't start until I open the portal and do something on the Azure Function (for example open the monitor for one of them).
In the code point of view, all functions with the timer trigger are defined like that:
[FunctionName("invoiceMonthlyGeneratorTimer")]
public void Run([TimerTrigger("%Timers:GenerateMonthlyInvoices%")] TimerInfo myTimer)
{
// ..
}
[FunctionName("invoiceDunningTimer")]
public async Task Run([TimerTrigger("%Timers:DunningTimer%")] TimerInfo timer)
{
// ...
}
The configuration of the timer is in the settings file like:
"Timers": {
"DunningTimer": "0 0 4 * * *",
"GenerateMonthlyInvoices": "0 0 4 * * *"
}
Generally, speaking, this approach was working in dev environment and it is working perfectly in the production environment.
Because each function sends an email, I expect each morning to find in my inbox some emails but it doesn't happen. Then, I open the Azure portal to see the logs and the monitor.
Open the Azure function in the portal.
Open the monitor for a function
Voila, after a couple of seconds, I start to receive the email for all services! In the production environment I don't have all the function I have in dev because I want to test before deploying. In prod the functions are working fine and start at the right time.
If I look at Application Insights, I can find only the logs for the time I opened the monitor.
There is one interesting thing in the log:
Trigger Details: UnscheduledInvocationReason: IsPastDue, OriginalSchedule: 2020-07-24T05:00:00.0000000+00:00
Update
Apparently, you can't have more than a couple of timer triggers in the same Azure Functions. I opened an issue on Github, so if other devs are facing the same. Something similar with HTTP triggers, look this post.
There are too many functions in your function app, they may interact each other. I met similar problem with this, in that case, the timer trigger functions in one function app and did not work. But when i deploy them to different function apps, they work fine. so you can try to deploy your second function to another function app.
And I suggest you report this problem to Microsoft, they can know more information about this problem, and may have a better solution.
Related
I have an Azure timer triggered function scheduled to run every 3 months in production. However in test environment I'd like it to run on start up, every time it is triggered.
At the moment I have:
[TimerTrigger("%TimerInterval%", RunOnStartup = false)]
I don't really want to change the RunonStartup to true but wondered if there's a way of setting this in the configuration?
Is it possible to do something like:
RunOnStartup = "%RunOnStartUpBool%" and set that in appsettings?
Update 2022-03-30: My previous answer was updating your code to use an #IF Debug pre-processor directive as a way to switch into the RunOnStartup=true method parameter. As of 2022, you can bypass that ungainly workaround and just select an option in the VS Code Azure Functions extension! That seems less complex. There is more information here.
Another alternative would be logging into the Azure portal, navigating to your function app and using the function's Test/Run tab.
OLD ANSWER: There is a good SO question with multiple answers to this same question here.
My test environment is normally my local environment. So if we want to write code that ONLY runs on your local environment and not in production we could use a a preprocessor directive in the middle of the method signature that only sets RunOnStartup=true when you are in the debug mode.
public static void Run([TimerTrigger("%TimerInterval%"
#if DEBUG
,RunOnStartup=true // When debugging... run the job as soon as we press debug, no need to wait for the timer.
#endif
)]TimerInfo myTimer)
{
Explanation: During local development (debug) the #if DEBUG block is activated.
It enables the RunOnStartup=true parameter. In production (not debug) the #if DEBUG block is hidden.
Clearly not the prettiest code. But much better than the alternatives ... such as having to wait on the timer trigger interval during dev.
You can not set RunOnStartup dynamically from configuration/environment variable at runtime. But you can solve your problem in some other way since your purpose is to trigger it manually at startup (or anytime). You can manually trigger the function by some specialized http call as described below. You can do that let's say from your deployment pipeline of test environment as a post deployment step (or any other means you prefer).
To run a non HTTP-triggered function (like in this case it's timer triggered), you need a way to send a request to Azure to run the function. The URL used to make this request takes a specific form.
Host name: The function app's public location that is made up from the function app's name plus azurewebsites.net or your custom domain.
Folder path: To access non HTTP-triggered functions via an HTTP request, you have to send the request through the folders admin/functions.
Function name: The name of the function you want to run.
You use this request location along with the function's "master key" as x-functions-key header in the POST request to Azure to run the function. Note Content-Type header should be set as application/json
For details, refer Manually run a non HTTP-triggered function
I have a c# exe that reads some log lines from a remote unix server using sed. when I run this exe several times on my windows server or even my dev pc, it executes fine. However, when I try to run it as a cyclic OS job in Control M eventually (sometimes at the first execution, seems to happen at random) it gets stuck but doesn't throw an exception or anything.
The command of the job runs a .bat file, and the cyclic is configured to 0 minutes with pause time being controlled dynamically by the exe with a thread.sleep.
after searching the web and seeking recommendation from other areas of my workplace that use control M, I have so far tried changing my agent to use local user with ctmwincfg, I also tried with changing the agent service to the same user (had to reverse this one as the agent stopped working properly), I also changed from directly executing my exe on the job to using a .bat file.
one of my hostgroup agents is windows server 2016 and 3 more are windows server 2012
I wasn't able of finding a solution within control M itself, but rather in the code of the .exe. I used a task, it allows the program to terminate the stuck method after a timeout, which in turn allows the control M job to finish normally.
var task = Task.Run(() => MyStuckMethod(arg));
if (task.Wait(TimeSpan.FromSeconds(30)))
return task.Result;
else
throw new Exception("Timed out");
Alternatively, there are a few workarounds within control M which involve sending alerts or creating shouts and then automating the kill of the job, but this is not useful for my case.
Example in BMC communities
I have a system for sending E-mails to users by a specific time .
built in ASP.NET MVC4 and has an action result "function" for checking the time of messages and send it if the day of the message is today .
how can I call this action result (daily) -like a scheduler- in efficient way ?
Thanks.
Whilst a separate service / application would be better, you could use wget.
GNU Wget is a free software package for retrieving files using HTTP,
HTTPS and FTP, the most widely-used Internet protocols. It is a
non-interactive commandline tool, so it may easily be called from
scripts, cron jobs, terminals without X-Windows support, etc.
You would then do something like:
"C:\Program Files (x86)\GnuWin32\bin\wget.exe" --no-check-certificate https://www.exammple.com/YouController/YourAction -O NUL
in a .bat file and set that to run via a windows Scheduled task at the time you require (assuming you don't need to run it less than every 60 seconds - if you do, let me know as I have another way around this using a windows service to call the bat file instead).
Omitting the -O NUL part would also save the output so you could see if everything ran successfully by doing:
public ActionResult YourAction()
{
//Do your code, get some stats that show it ran properly.
return Content("Return your stats here.");
}
from your controller action.
More efficient will be when you create new application as Windows Service. There u can easy set code to start at specific time. in this solution you will have more flexibility and independent. You can start hire : Windows Service to run a function at specified time
You could create a small console application that just calls the API do send out the emails. You can then schedule the console app to run at a specific time using the Windows Scheduler; you can even have it run without showing the console window. See here or here for details on how to schedule a task.
Use Azure Functions, that's exactly what it was built for. It's really good.
https://learn.microsoft.com/en-us/azure/azure-functions/functions-overview
I need some guidance on creating and running a Cron Job in asp.net(C#.net) to run every 30 minutes.i have created a class in that i have written code for getting tweets, facebook feeds.
i have created another page in that i have one button to download tweets and save in database.
If i want to get tweets i have to click on sync button every time.
i want to create cron job so that the database will get automatically synchronized with new tweets,facebook feeds.
Thanks
You can follow any one of the following approaches
Create a console app with the logic to fetch the tweets and feeds, and use a Task scheduler to run it for every 30 mins.
You could build a windows service, which polls the feeds within a timer and updates the db.
You could checkout this scheduler which is a rough equivalent to cron jobs. Personally haven't tried it. Check out this SO
If your intended 30-minute scheduled task is meant to be a discrete transactional action (like, for instance, your example of synchronizing some database values), then you may want to take a look at the Revalee open source project.
You can use it to schedule web callbacks at specific times. In your case, you could schedule a web callback (30 minutes in the future). When your ASP.NET application receives the callback, it can schedule the next 30 minute callback as well as perform whatever tasks you need it to handle every half-hour. When your ASP.NET application launches for the very first time, then you would schedule the first web callback. Since your web application is being called back, you do not need to worry about your web application unloading (which it will do periodically on IIS, for example).
For example using Revalee, you might do the following:
Register a future (30 minutes from now) callback when your application launches via the ScheduleThirtyMinuteCallback() method (see below).
private DateTimeOffet? previousCallbackTime = null;
private void ScheduleThirtyMinuteCallback()
{
// Schedule your callback 30 minutes from now
DateTimeOffset callbackTime = DateTimeOffset.Now.AddMinutes(30.0);
// Your web service's Uri, including any query string parameters your app might need
Uri callbackUrl = new Uri("http://yourwebapp.com/Callback.aspx");
// Register the callback request with the Revalee service
RevaleeRegistrar.ScheduleCallback(callbackTime, callbackUrl);
previousCallbackTime = callbackTime;
}
When the web scheduled task activates and calls your application back, you perform whatever action you need to do every 30 minutes and you schedule the next callback too. You do this by adding the following method call (CallbackMonitor()) to your Callback.aspx page handler.
private void CallbackMonitor()
{
if (!previousCallbackTime.HasValue
|| previousCallbackTime.Value <= DateTimeOffset.Now.AddMinutes(-30.0))
{
// Perform your "30 minutes have elapsed"-related tasks
// ...do your work here...
// Schedule subsequent 30 minute callback
ScheduleThirtyMinuteCallback();
}
}
To be clear, the Revalee Service is not an external 3rd party online scheduler service, but instead a Windows Service that you install and fully control on your own network. It resides and runs on a server of your own choosing, most likely your web server (but this is not a requirement), where it can receive callback registration requests from your ASP.NET application.
If, however, your 'run every 30 minutes' task is a long running task, then you probably do not want to embed that functionality within your ASP.NET application.
I hope this helps.
Disclaimer: I was one of the developers involved with the Revalee project. To be clear, however, Revalee is free, open source software. The source code is available on GitHub.
I would like to run a time consuming script (to update a database from a 3rd party API) at regular intervals. I was wondering what the best practice for this would be:
What should the 'script' be - an ASP.NET service? Bearing in mind I am on shared hosting, this may not be possible (but I would like to know).
How could the script be scheduled to run at regular intervals/at set time automatically?
Thanks in advance!
Some options for this:
Use a separate thread that keeps running all the time - and does the update on time (and then sleeps).
Use a timer and trigger the update event.
Use a Cache expiration trigger, but test this so that it keeps running without users visiting the site.
I would suggest checking out http://www.beansoftware.com/ASP.NET-Tutorials/Scheduled-Tasks.aspx for more details on these methods.
There is no way you can guarantee that something runs e.g. every night in a normal IIS setup. Batch jobs are thus a pain to handle. The only "mode" of execution for IIS is requests. If your application has no requests it doesn't run at all so IIS does not spend any resources on executing code in your application, i.e. it can unload it entirely.
If you have your own host, you would typically create a windows service to run your background tasks. I believe the same is possible in Azure. But for a standard sharesd IIS host, you basically can't setup a scheduled background task.
One of the simplest hacks is to setup a protected service that executes the job when it gets a request. Then you can make sure an external caller calls into your service at the required intervals.
What you can do is add a System.Timers.Timer in Global.asax.
System.Threading.Timer timer = new System.Threading.Timer(new TimerCallback(TimerElapsed), null, new Timespan(0), new Timespan(24, 0, 0));
// This will run every 24 hours.
private void TimerElapsed(object o)
{
// Do stuff.
}
In IISManager, enable HTTP-Keep Alives for your application.
In IIS Manager, select Http Response Headers Module, open it and in the Actions Pane, select Set Common Headers and in there select Enable Http Keep Alives.
Also, check for a setting of your application pool -
Select the application pool of your application, select Advanced Settings from the right Actions Tab.
In there there is a setting called - Idle Timeout (minutes)
By default it is 20 Minutes. Make it something like 60 Minutes or increase it even more and check.