Looking for some self triggering function which starts on a time given.
eg. A user has a conference to start at 25/04/2019 05:30
Here the user should get a notification at 25/04/2019 05:25 | 05:29 That the conference is about to start.
Have created a azure function (Time triggred) which triggers every minute and checks if current time is the Conference Time - 4 minutes, Then send a notification regarding conference to be started.
In future will have multiple users and so I do not want the function to run every minute, Is there a way in which at 05:25 or at the conference time the function will execute itself.
So there can be 100 users and they will have different. Just looking for options about how to implement in a better way.
.net core site,
hosted on azure,
Have azure functions running every minute to check the remainder
When user registered on conference you can queue message(with user details) to queue with visibility delay:
queue.AddMessage(message, initialVisibilityDelay: TimeSpanDelay);
For example, user registered at 6 PM, and conference will be next day at 8 PM, so delay time will be 25 hours and and 55 minutes(supposed, that user want to be notified 5 minutes before conference). Then instead of time triggered function you will use queue triggered function, which will send notifications, when messages from queue become visible:
public static void Run([QueueTrigger("notifications")]QueueTrigger message, TraceWriter log)
{
Notifier.Send(message.UserName, message.UserPhoneNumber, message.Email);
}
Moreover, if by some reason your notification handler will be failed, queue messages will not be lost, so you can retry to process them several times.
I recommend you to write a windows service using quartz library to schedule a job. You can pickup the job schedule time from db or somewhere.
Refer: https://www.quartz-scheduler.net
From your description, you already have a TimerTrigger Function however your Timer set the function running every minutes. Actually you could set more precise Timer trigger with CRON expressions.
This is CRON expressions in Azure Function, it includes six fields:{second} {minute} {hour} {day} {month} {day-of-week}. So you could set your Function 0 25,29 5 22 March *.
And after you deploy the function to Azure, it will keep running however it won't execute the Run method until it triggers the Timer.
public static void Run(TimerInfo myTimer, ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
}
Related
Suppose I have a service fabric reminder which I registered via OnActivateAsync method. Now for these Service Fabric reminder via GetReminder method I can check whether a reminder already exists or not. But can I check when is this reminder scheduled to trigger next ?
For example I have registered a reminder with a period of 4 hours and it got triggered at 2PM ( schedule to trigger next at 6PM ). Now at 3:30 PM some of my other service want to know when is the next reminder scheduled. I can get this reminder via GetReminder method but I am unable to get the time remaining for its next execution.
Following this Doc - Actor timers and reminders
Use the reminder due date. Add periods while the result is smaller than the current time.
The first time it is larger, the difference is the time remaining until it fires next.
Scenario: A Azure WebJob that will get all the Vendor record from NetSuite via WSDL.
Problem: The dataset is too large. Even with service set to 12 minutes time out. It still time out and the code failed.
NetSuite have a async process that basically run whatever you want on the server and it will return a JobId that allowed you to check the process on the server.
What I did currently is by making a search call first asking for all the Vendor records and it is to be process on the server. After I got the JobId, i wrote a void Recursion that check if the job is finish on the server with Thread Sleep set to 10 minutes.
private static bool ChkProcess(VendorsService vendorService, string jobId)
{
var isJobDone = false;
//Recursion
void ChkAsyncProgress(bool isFinish)
{
if (isFinish) return;
var chkJobProgress = vendorService.NsCheckProcessStatus(jobId);
if (chkJobProgress.OperationResult.IsFinish) isJobDone = true;
Thread.Sleep(TimeSpan.FromMinutes(10));
ChkAsyncProgress(isJobDone);
}
ChkAsyncProgress(false);
return isJobDone;
}
It work but is there a better approach?
Thanks
I think that since you're working with Azure already, with Service BUS you can implement a really low cost solution for this (if not free, depending on how much frequent is your job running)
Basically it's a queue where you enqueue messages (which can be objects with properties too, so they could also contain your result of the elaboration potentially).
A service bus is used to enqueue.
An azure function of type ServiceBusTrigger listens automatically if any new message on service bus has arrived and gets triggered if so (or, you can set messages to be enqueued, but be available after a certain future time only).
So, in the webjob code, at the end you could add code to enqueue a message which will mark the webjob has finished elaboration.
The azure function will get immediately noticed as soon as the message gets in the queue and you can retrieve the data without polling constantly for job completion, as azure will take care of all of that for you for a ridiculous price and without any effort by you.
Also, these task aren't priced timely based, but execution based, so you will pay only when it effectively put a message in queue.
They have a certain number of executions free, so it might be that you don't even need to pay anything.
Here some microsoft code sample for doing so.
I observed this strange issue with azure function which is triggered by a service bus queue message.
Azure function is continuous running which is trigger when service bus queue gets new message.
but when there is no message into queue for long time like suppose
1-2 days and when new message come into queue after 2 days ,Its
strange that azure function does not get triggered , why any clue?
public static class TestController
{
[FunctionName("TestController")]
public static async Task Run([ServiceBusTrigger("%TestController.Topic%", "%TestController.Subscription%", AccessRights.Listen,
Connection = "ConnServiceBus")]BrokeredMessage currentMessage, TraceWriter log, ExecutionContext context)
{
log.Info("TestControllerprocessing start " + DateTime.Now);
Try force resyncing your triggers by hitting the Refresh button. This is a known issue for Azure Functions that are idle for a nondeterministic period of time. Also, verify if you're seeing the messages in the dead letter queue.
Prevent your Azure Function from going idle to begin by enabling "Always On": Open your Function App in the Azure portal. Click on Function App Settings at the top of the Function App blade. Scroll to the bottom of the page and click on Go to App Service Settings. In the Settings blade, scroll down and click on Application Settings. In the Application Settings blade, make sure that the Always On setting is set to On.
Azure Functions have a time limit of 10 minutes. Suppose I have a long-running task such as downloading a file that takes 1 hr to download.
[FunctionName("PerformDownload")]
[return: Queue("download-path-queue")]
public static async Task<string> RunAsync([QueueTrigger("download-url-queue")] string url, TraceWriter log)
{
string downloadPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString);
log.Info($"Downloading file at url {url} to {downloadPath} ...");
using (var client = new WebClient())
{
await client.DownloadFileAsync(new Uri(url), myLocalFilePath);
}
log.Info("Finished!");
}
Is there any hacky way to make something like this start and then resume in another function before the time limit expires? Or is there a better way altogether to integrate some long task like this into a workflow that uses Azure Functions?
(On a slightly related note, is plain Azure Web Jobs obsolete? I can't find it under Resources.)
Adding for others who might come across this post: Workflows composed of several Azure Functions can be created in code using the Durable Functions extension, which can be used to create orchestration functions that schedule async tasks, shut down, and are reawakened when said async work is complete.
They're not a direct solution for long-running tasks that require an open TCP port, such as downloading a file, (for that, a function running on an App Service Plan has no execution time limit), but it can be used to integrate such tasks into a larger workflow.
Is there any hacky way to make something like this start and then
resume in another function before the time limit expires?
If you are on a Consumption Plan you have no control over how long your Function App runs, and so it would not be reliable to use background threads that continue running after your Function entry point completes.
On an App Service plan you're running on VMs you pay for, so you can configure your Function App to run continuously. Also AFAIK you don't have to have a Function timeout on an App Service Plan, so your main Function entry point can run for as long as you want.
Or is there a better way altogether to integrate some long task like this into a workflow that uses Azure Functions?
Yes. Use Azure Data Factory to copy data into Blob Storage, and then process it. The Data Factory pipeline can call Functions both before and after the copy activity.
One additional option, depending on the details of your workload, is to take advantage of Azure Container Instances. You can have your Azure Function spin up a container, process your workload (download your file \ do some processing, etc), and then shut down your container for you. Spin up time is typically a few seconds and you only pay for what you use (no need for a dedicated app service plan or vm instance). More details on ACI here.
10 minutes (based on the timeout setting in the host.json file) after the last function of your function app has been triggered, the VM running your function app will stop.
To prevent this behavior to happen, you can have an empty Timertrigger function that runs every 5 minutes. it wont cost anything and will keep your app up and running.
I think the issue is related with the Cold Start state. Here you can find more details about it.
https://markheath.net/post/avoiding-azure-functions-cold-starts
What you can do is, create an trigger azure function that "ping" your long running function to keep it "warm"
namespace NewProject
{
public static class PingTimer
{
[FunctionName("PingTimer")]
public static async Task Run([TimerTrigger("0 */4 * * * *")]TimerInfo myTimer, TraceWriter log)
{
// This CRON job executes every 4 minutes
log.Info($"PingTimer function executed at: {DateTime.Now}");
var client = new HttpClient();
string url = #"<Azure function URL>";
var result = await client.GetAsync(new Uri(url));
log.Info($"PingTimer function executed completed at: {DateTime.Now}");
}
}}
in my web-application I want to send mail for users according to pre selected periods by themselves. for example: 1 HTML Mail Per 3days to user 01 and 1 HTML Mail Per 20days to user 02
how can I perform that? any resources? I can send mail by my app from My Gmail Account to any mail addresses in my tables but i dont know how to send it automatically in a period of time.(i use C# and SQL Express)
Help me out!
I found the Solution. according to my search we have 3 ways to handle that:
working with SQL Server to send mail notification in periods of time.(or this)
using Windows service and Creating Timer object and checking the time with it.
but in ways 1 and 2 we should access to server and we need dedicated hosting server to for example installing WinService on it. so it does not work in a sharing Host space we usually use. So I Found the best way as you see:
3. Simulating Windows Services Using ASP.NET Caching For Scheduled Jobs.
the link above is a terrific solution. So there is no need to work out-side of our web application.
You will need something which can periodically run jobs for you, like a cron daemon or windows task scheduler.
Essentially you have the periodic job kick off and do whatever mail handling you need.
You can also do this from code if you can create a windows service to basically sleep until the next batch of mails needs to be sent.
The easiest is to write the task scheduler or cron job to run periodically. In that way you just need a small piece of code to handle the mail sending portion and then you just schedule it to run once an hour or day or whatever needed.
Hai,
Have a look at quartz.net
Quartz.NET is a full-featured, open source job scheduling system that can be used from smallest apps to large scale enterprise systems.
Quartz.NET is a port of very propular open source Java job scheduling framework, Quartz. Quartz.NET supports clustering and database persistence out-of-the-box and has powerful means to schedule jobs using cron like expressions, interval triggers and exclusion advices.
The great thing about IIS hosted ASP.NET is that IIS will (by default) periodically recycle your application pool according to the settings on the app pool itself.
When your application pool is starting (which could be at least once a day especially if it's allowed to idle i.e. a business app where most activity is 9-5) the Application_Start event-handler in Global.asax is fired. This could be used for your recurring task.
Now you don't necessarily want to run this email send synchronously within that Application_Start handler because to me it seems this messaging functionality is not core to the startup but by all means use this event-handler as an easy way to periodically do your housekeeping.
To send async you should use async delegates for example.
i think there a solution:
1- you have to add 2 column in the user table in your sql db if you have a user table and in the first column add the date of the last email sent to the user and the second column has the period for sending the email for that user for ex:
LastEmailSentDate datetime
SendEmailPeriod int
2- in your application code write a function that compare the last date of the last sent email with the period of the sending the email.
// here the funciton code
public void CompareLastSentDate()
{
// lets assume that you bring the data for the db using Sqdatareader reader
//get the field from the LastEmailSentDate field in the database as i mention before
DateTime LastEmailSentDate = Convert.ToDate(reader["DatePeriod"])
// get the field from the SendEmailPeriod of the user field from database
int sendEmailPeriod = Convert.Toint32(reader["SendEmailPeriod"])
// now you have the date before the period of day ex: before 3 days depend on user
DateTime DatePeriod = new DateTime(DateTime.Now.Year, DateTime.Now.Month, (DateTime.Now.Day - sendEmailPeriod ));
// if the last email send is before period of day that mean u have to send an email again
if(LastEmailSentDate.Day <= DatePeriod.Day)
{
// sent the email to the user
}
}
note: now u can loop among the users and sent the email
you can call this function once in a day by calling it from ur app home page Page_Load event and after the first call of the day add an application["LastFunctionCallDate"] = DateTime.Now flag so in the next you can check this flag if its == today and if not call it again