Simplest Way to Schedule Multiple Webjobs from DevOps - asp.net

I have an app service in Azure running the front end from my MVC5 app, and another app service for web jobs. The app has several endpoints (GET Actions) which do some processing, send some emails or other simple task. Previously when we were hosted on a VPS, we used the Windows Task Scheduler to call each URL on a custom schedule. In Azure, the way we're currently doing this is with a Powershell script which uses CURL to fetch the URL and trigger the processing.
It seems messy though - as each powershell script has to be uploaded individually, and can't be viewed or changed after uploading. I've found various guides on deploying a .NET Core console app, but from what I can tell each job would need it's own project, deployed with it's own pipeline.
Is there a nicer way of doing this, are Webjobs even the right tool for this job, given the seemingly simple task we're performing.

As far as I understand your use case, you can use Azure Function App Timer Trigger to accomplish it.
A timer trigger lets you run a function on a schedule.
The following example shows a C# function that is executed each time the minutes have a value divisible by five (eg if the function starts at 18:57:00, the next performance will be at 19:00:00). The TimerInfo object is passed into the function.
[FunctionName("TimerTriggerCSharp")]
public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, ILogger log)
{
if (myTimer.IsPastDue)
{
log.LogInformation("Timer is running late!");
}
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
}
The attribute's constructor takes a CRON expression or a TimeSpan. You can use TimeSpan only if the function app is running on an App Service plan. TimeSpan is not supported for Consumption or Elastic Premium Functions.
CRON (NCRONTAB expressions)

Related

How to deploy Firebase Cloud functions programmatically, to be run at a specific time?

Usually functions are deployed via CLI, calling the firebase deploy -only functions:my_function.
Is it possible to deploy functions programmatically (hence dynamically)?
In my use case I would like to re-schedule a PubSub to run after a specific amount of time, relative to the current execution time, rather than regularly every time interval.
The same way as setTimeout would work (rather than a setInterval), but without having a process running and waiting to call the function.
What would be the drawbacks?
What would be alternative ways to achieve a similar result with what Firebase provides?
You already deploy that Cloud Function programmatically by issuing a command.
Generally there's repeated and delayed execution available.
a) Cloud Scheduler crontab receives scheduled Pub/Sub events:
exports.cronjob = functions.pubsub.schedule('0 */12 * * *').onRun(async context => {
...
});
b) Cloud Tasks may be better to schedule at a specific time.

AzureFunctions: How to make a sync call to a QueueTrigger Function for an automated functional test

Let me introduce the scenario:
I need to test an AzureFunction with a queue trigger:
[FunctionName("AFunction")]
public async Task DispatchAction([QueueTrigger("queuename")] string message)
{
await DoMyLogicAsync();
}
The test needs to be run by the "functional-test-container" in my docker-compose testing env, which is made up by:
a) functional-test-container: a .net core container running an nUnit test suite
b) azure-function-container: this container hosts the azure function
c) azurite-container: this container hosts the queue server
d) sql-server-container
e) wiremock-container
The test logic is the following:
Clear the sql database, the queue and wiremock status
Prepare the wiremock stubs
Somehow trigger the function
wait for the function to end
make assertions on what the function produced in sql server, in the queue and on what wiremock's stubs have been called
As far as I know I have 2 ways of triggering the function:
a) pushing a message in the queue
b) using azure function's admin API /admin/functions/afunction
the problem is that both of them don't give any hint on when the function ends its execution.
Here it is my question: is there a way to call the function in a "sync" way (so that I can know when the execution ends)?
I don't think it can be implemented. The queue trigger function runs as an instance in azure server, we can just trigger it to run. It doesn't response any data like HttpTrigger function. So it can't be executed synchronously in your entire process.
To solve your problem, I think you can just add some code to do an operation at the end of your function. The operation is used to let you know the function execution is completed. Or another solution is move the steps after function into your function code.

How to read Cron Expression from appsettings.json in .Net core Web Jobs

I have developed .Net Core 2.2 Azure Web Job project which is having multiple timer trigger functions. One function is run on every 15 minutes and other one is run on every 10 minutes.
public async Task GetRecordsFromCosmosDBCollection_0([TimerTrigger("0 0/15 * * * *")]TimerInfo timerInfo){
//Custom Business Logic
}
public async Task GetRecordsFromCosmosDBCollection_1([TimerTrigger("0 0/10 * * * *")]TimerInfo timerInfo){
//Custom Business Logic
}
If I used the CRON expression directly in the function parameters then it works as expected. But I want to read the CRON expression information from appsettings.json file and then pass it to the above two functions.
So, can anyone suggest the right approach of reading the CRON expression information from appsettings.json in Functions.cs file in Azure WebJob project.
I assume the motivation is to get the schedule out of the compiled code where it can be changed without having to re-compile and re-deploy.
This might not be the most elegant solution - but you could put your two functions into two different scheduled WebJobs. Then you could set a separate settings.job for each one.
https://learn.microsoft.com/en-us/azure/app-service/webjobs-create#CreateScheduledCRON
The external settings.job file is deployed to the folder where the WebJob exe is - typically D:\home\site\wwwroot\App_Data\jobs\triggered\WebJobName - and you could change the schedule there.
To have different schedules - you'd have to split into different WebJobs because the settings.job schedule is kicking off Main, as opposed to a specific function like [TimerTrigger].
In a scheduled job, the code in Main would look like this:
await host.StartAsync();
await jobHost.CallAsync("ManualTrigger", inputs);
await host.StopAsync();
where "ManualTrigger" is the function in Functions.cs. The schedule in settings.jobs kicks off Main, runs the function, and then shuts down.

For Hangfire, is there any sample code for non-simple tasks; and how should recurring tasks be handled when re-publishing?

I am considering using Hangfire https://www.hangfire.io to replace an older home-grown scheduling ASP.NET web site/app.
I have created a simple test project using Hangfire. I am able to start the project with Hangfire, submit (in code) a couple of very simple single and recurring tasks, view the dashboard, etc.
I'm looking for more suggestions for creating a little more complex code (and classes) for tasks to be scheduled, and I have a question about what happens with permanently scheduled tasks when re-publishing a Hangfire site to production.
I have read some of the documentation on the Hangfire site, reviewed the 2 tutorials, scanned the Hangfire forums, and searched StackOverflow and the web a bit. A lot of what I have seen shows you how to schedule something very simple (like Console.WriteLine), but nothing more complex. The "Highlighter" tutorial was useful, but that essentially shows how to schedule a single instance of a (slightly longer-running) task in response to an interactive user input. I understand how useful that can be, but I'm more interested in recurring tasks that are submitted and then run every day (or every hour, etc.) and don't need to be submitted again. These tasks could be for something like sending a batch of emails to users each night, batch processing some data, importing a nightly feed of external data, periodically calling a web service to perform some processing, etc.
Is there any sample code available that shows some examples like this, or any guidance on the most appropriate approach for structuring such code in an interface and class(es)?
Secondly, in my case, most of the tasks would be "permanent" (always existing as a recurring task). If I set up code to add these as recurring tasks shortly after starting the Hangfire application in production, how should I handle it when publishing updates to production (when this same initialization would run again)? Should I just call "AddOrUpdate" with the same ID and Hangfire will take care of it? Should I first call "RemoveIfExists" and then add the recurring task again? Is there some other approach that should be used?
One example would be a log janitor, which would run every weekday # 5:00PM to remove logs that are older than 5 days.
public void Schedule()
{
RecurringJob.AddOrUpdate<LogJanitor>(
"Janitor - Old Logs",
j => j.OnSchedule(null),
"0 17 * * 1,2,3,4,5",
TimeZoneInfo.FindSystemTimeZoneById("CST"));
}
Then we would handle it this way
public void OnSchedule(
PerformContext context)
{
DateTime timeStamp = DateTime.Today.AddDays(-5);
_logRepo.FindAndDelete(from: DateTime.MinValue, to: timeStamp);
}
These two methods are declared inside LogJanitor class. When our application starts, we get an instance of this class then call Schedule().

How to give a web request to windows task Scheduler

I have a static webmethod i.e (http://localhost:61176/trunk/MusteriKontrol.aspx/CheckMusteri) I want to call this method from Windows Task Scheduler. How should I do this?
You could use a PowerShell script. This has a check for the time, a commented-out Try..Catch in case you want to do something if an error is raised from the query, and records when it has run in the Application event log:
# Download the HTML of a web page.
# Make sure an event log source is created with New-EventLog -LogName Application -Source MyPSscript
# Only do this if the time is 5a.m. or later, to give the server a rest from midnight.
$currHour = (Get-Date).Hour
if ($currHour -ge 5) {
$web = New-Object Net.WebClient
#try {
$temp = $web.DownloadString("http://localhost:61176/trunk/MusteriKontrol.aspx/CheckMusteri")
#}
#catch {
# do nothing.
#}
write-eventlog -logname Application -source MyPSscript -eventID 1001 -entrytype Information -message "Fetched web page." -category 0
}
Have considered a different alternative to scheduling the call of a web method from Windows Task Scheduler?
For example, scheduling tasks from within an ASP.NET project is possible using the Revalee open source project.
Revalee is a service that allows you to schedule web callbacks to your web application. In your case, you would schedule a callback that would call your web method at a specific time. Revalee works very well with tasks that are discrete transactional actions, like updating some database values or sending an automated email message (read: not long running). The upside is that the code that schedules the callback, as well as the code that performs your action (i.e., your web method), would all reside within your app.
To use Revalee, you would:
Install the Revalee Service, a Windows Service, on your server. The Windows Service is available in the source code (which you would compile yourself) or in a precompiled version available at the Revalee website.
Use the Revalee client library in your Visual Studio project. (There is an MVC-specific version too.) The client library is available in the source code (which, again, you would compile yourself) or in a precompiled version available via NuGet.
You would register a future callback when your code calls the ScheduleWebMethodCallback() method (this example is assuming that you need your action to run 12 hours from now).
private void ScheduleWebMethodCallback()
{
DateTimeOffset callbackTime = DateTimeOffset.Now.AddHours(12.0);
// The callback should be in 12 hours from now
Uri callbackUrl = new Uri(string.Format("http://localhost:61176/trunk/MusteriKontrol.aspx/CheckMusteri"));
// Register the callback request with the Revalee service
RevaleeRegistrar.ScheduleCallback(callbackTime, callbackUrl);
}
When Revalee calls your application back, your app would perform whatever action you have coded it to do in the web method you have listed above.
In case it was not clear above, 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.
I hope this helps.
Note: The code example above uses a synchronous version of ScheduleCallback(), the Revalee client library also supports asynchronous calls à la:
RevaleeRegistrar.ScheduleCallbackAsync(callbackTime, callbackUrl);
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.

Resources