How to trigger multiple c# functions in a particular time in specific order using azure function? - c#

I have created two functions which triggered on everyday at specific time (2:00 AM) but both functions triggered independently on specific time in azure function.
I have tried following working example which function1 and function2 triggered everyday at specific time (2:00 AM)
[FunctionName("Function1")]
public static void Method1([TimerTrigger("0 0 2 * * *")] TimerInfo myTimer, ILogger log)
{
log.LogInformation($"Function 1: {DateTime.Now}");
}
[FunctionName("Function2")]
public static void Method2([TimerTrigger("0 0 2 * * *")] TimerInfo myTimer, ILogger log)
{
log.LogInformation($"Function 2: { DateTime.Now}");
}
but both function triggered independently,
For example First time I executed code, following function order was displayed which is expected result -
Function1: 5/11/2021 02:00:00 AM
Function2: 5/11/2021 02:00:00 AM
but Second time I again execute code than following function order was displayed -
Function2: 5/11/2021 02:00:00 AM
Function1: 5/11/2021 02:00:00 AM
EXPECTED RESULT:-
Both functions should be triggered at 2:00 AM such that function1 triggers first and after that function2 should be trigger as following order -
Function1: 5/11/2021 02:00:00 AM
Function2: 5/11/2021 02:00:00 AM
How to trigger multiple functions in a particular time in specific order using azure function?

Although you set the Function1 at first and set Function2 at second, but they will be triggered independently as you test.
If you want them be triggered in order, why not put two function execution code into one function(execute the first part of code then execute the second part of code) ?
Or another option is modify the cron expression of second function to: 0 1 2 * * *, then it will be trigger at 2:01 AM.

Related

Azure TimerTrigger is not working in .NET 7 Isolated Worker Process

I'm trying to trigger an orchestrated function TimerTrigger in .NET 7. Below is the function I created
[Function(nameof(FunctionSampleTimer))]
public async Task Run([TimerTrigger("*/5 * * * * *", RunOnStartup = false)] MyInfo myTimer, [DurableClient] DurableTaskClient client, FunctionContext context)
{
var instanceid = Guid.NewGuid().ToString();
var logger = context.GetLogger("TimerFunction");
logger.LogInformation($"Function Ran. Next timer schedule = {myTimer.ScheduleStatus.Next}");
}
The above function is getting triggered once every 5 seconds only for the first time when the project is created, and is not getting triggered again and getting stuck on that "Host lock lease acquired..." line.
Console output shows this:
[2023-02-20T01:26:52.843Z] Azure Functions .NET Worker (PID: 49120) initialized in debug mode. Waiting for debugger to attach...
[2023-02-20T01:26:53.305Z] The next 5 occurrences of the 'FunctionSampleTimer' schedule (Cron: '0,5,10,15,20,25,30,35,40,45,50,55 * * * * *') will be:
[2023-02-20T01:26:53.307Z] 02/19/2023 17:26:55-08:00 (02/20/2023 01:26:55Z)
[2023-02-20T01:26:53.308Z] 02/19/2023 17:27:00-08:00 (02/20/2023 01:27:00Z)
[2023-02-20T01:26:53.309Z] 02/19/2023 17:27:05-08:00 (02/20/2023 01:27:05Z)
[2023-02-20T01:26:53.310Z] 02/19/2023 17:27:10-08:00 (02/20/2023 01:27:10Z)
[2023-02-20T01:26:53.311Z] 02/19/2023 17:27:15-08:00 (02/20/2023 01:27:15Z)
[2023-02-20T01:26:53.312Z]
[2023-02-20T01:26:53.323Z] Host started (775ms)
[2023-02-20T01:26:53.324Z] Job host started
[2023-02-20T01:26:54.472Z] {
[2023-02-20T01:26:54.473Z] "ProcessId": 49120,
[2023-02-20T01:26:54.474Z] "RuntimeIdentifier": "win10-x64",
[2023-02-20T01:26:54.475Z] "WorkerVersion": "1.8.0.0",
[2023-02-20T01:26:54.476Z] "ProductVersion": "1.8.0-local202209270007\u002B04ccbd8e45bb9017dc30ff5e1343e893a216e173",
[2023-02-20T01:26:54.477Z] "FrameworkDescription": ".NET 7.0.0",
[2023-02-20T01:26:54.478Z] "OSDescription": "Microsoft Windows 10.0.22621",
[2023-02-20T01:26:54.479Z] "OSArchitecture": "X64",
[2023-02-20T01:26:54.480Z] "CommandLine": "C:\\Users\\swkandhi\\source\\repos\\FunctionTimerTrigger\\FunctionTimerTrigger\\bin\\Debug\\net7.0\\FunctionTimerTrigger.dll --host 127.0.0.1 --port 58647 --workerId e70ddb42-819a-45b2-a17c-dca35392699d --requestId 326e359b-9d29-4105-b2f1-9ef01892ae95 --grpcMaxMessageLength 2147483647"
[2023-02-20T01:26:54.481Z] }
[2023-02-20T01:26:54.493Z] Worker process started and initialized.
[2023-02-20T01:26:55.053Z] Executing 'Functions.FunctionSampleTimer' (Reason='Timer fired at 2023-02-19T17:26:55.0194750-08:00', Id=872452e5-4d71-42ea-a16d-d4790ccf38a2)
[2023-02-20T01:26:57.821Z] Host lock lease acquired by instance ID '00000000000000000000000074E57A56'.
With what you have there for timing (5 * * * * *) I think it means it should run once at the 5 second mark. If you want it to run every 5 seconds you should do this (*/5 * * * * *)
I have observed for every minute and couple of minutes in .NET 7 Isolated Azure Functions with generating the GUID Id, it is working successfully:
Below are my test cases:
For every
1st Run
Next Runs
2 minutes
Yes
Yes
1 minute
Yes
Yes
60 seconds
Yes
Yes
30 Seconds
Yes
No
5 Seconds
Yes
No
For every minute:
For every 2 minutes:
For every 60 Seconds:
For every 5 Seconds:
AFAIK, the shortest interval requires at least 60 seconds minimum in the CRON Expression - the same is mentioned in the articles of Hostinger - Cron Job Tutorial.

Debug Azure Function locally with Visual Studio 2019

I want to run a task every day at 5 am to write some data to the database to create some reports. For that I thought I could use Azure Functions (Timer trigger). My goal is to first debug the function locally (using a local database) before publishing it to Azure. For this I have created a new Azure Functions project in Visual Studio 2019 with the following parameters:
.NET 5.0 (Isolated).
Timer trigger.
Storage Account (AzureWebJobsStorage): Storage Emulator.
Schedule: 0 0 5 * * *
If I try to run the function (pressing F5 in the keyboard) without any changes to the code, it opens a CMD window with the colored Azure Functions logo created with characters and then the following error:
Error: unknown argument --port
In project properties > Debug tab > Application arguments I have --port 7282. I have a systray icon with this message: "Storage emulator is started".
I tried the answer of What is the simplest way to run a timer-triggered Azure Function locally once? question, but I get the same error.
What do I have to do to debug the function locally? Do I need to install any specific tool?
If it helps, I have the following files:
Program.cs
public class Program
{
public static void Main()
{
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.Build();
host.Run();
}
}
Function1.cs:
public class Function1
{
private readonly ILogger _logger;
public Function1(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<Function1>();
}
[Function("Function1")]
public void Run([TimerTrigger("0 0 5 * * *")] MyInfo myTimer)
{
_logger.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
_logger.LogInformation($"Next timer schedule at: {myTimer.ScheduleStatus.Next}");
}
}
public class MyInfo { ... }
public class MyScheduleStatus { ... }
Why is port sat ?
What happens if you remove the --port (can't comment due to my low rep. There for I try to give the answer)
Then try to add RunOnStartup=true to your Function parameter as such:
[Function("Function1")]
public void Run([TimerTrigger("0 0 5 * * *") RunOnStartup=true] MyInfo myTimer)
{
_logger.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
_logger.LogInformation($"Next timer schedule at: {myTimer.ScheduleStatus.Next}");
}
That should trigger it to run at start up for your application.
Have you looked at the MS Learn docs
Edit: typo

How to run functionality only sometimes in an Azure function

I have an Azure function with a trigger to make it run once every 15 minutes:
TimerTrigger("0 */15 * * * *", RunOnStartup =false)
Within this function, there is some functionality that I only want to run once per hour. I am currently checking the minute of the current time to see whether it should run or not. But as I understand it, Azure function triggers are not always precise (this is running on a consumption-based app service), so instead I am checking for a range of minutes.
int currentMinute = DateTime.Now.Minute;
bool extraFunctionality = (currentMinute >= 58 && currentMinute <= 2);
This seems like it will work; only running this functionality during the ":00" runs, once per hour. However, it looks like bad code to me, for a couple reasons:
The up to 2 minutes early and 2 minutes late number was chosen pretty much arbitrarily; I don't have a good idea of what sort of time span to use there.
It relies on using DateTime.Now which will return different results depending on server settings, even though I don't care about anything other than the current minute.
The code simply doesn't read like the intent is to get it to run once per hour.
Is there a better / more proper way to do this within Azure functions? Can I either get information from the TimerInfo parameter or the ExecutionContext parameter about which 15-minute trigger caused the function to run? Or can I have a separate TimerTrigger which runs once per hour, and then have different functionality based on which of the 2 timers caused the function to trigger? Or is there some way to have the TimerTrigger itself pass in a parameter telling me which 15-minute window it is in?
Or, is my code fine as-is; perhaps with some adjustment to the number of minutes I allow it to be off?
You could create two Azure Functions, one which runs at 15, 30, 45 minutes past the hour and another which runs on the hour. Then in each of these functions set a variable for if it's runnin on the hour.
[FunctionName("HourlyFunction")]
public static void RunHourly([TimerTrigger("0 0 15,30,45 * * *")]TimerInfo myTimer, ILogger log)
{
_myService.Run(true);
}
[FunctionName("FifteenMinuteFunction")]
public static void RunEveryFifteen([TimerTrigger("0 0 * * * *")]TimerInfo myTimer, ILogger log)
{
_myService.Run(false);
}
Then have a separate service which can be called by those functions:
public class MyService : IMyService
{
public async Task Run(bool isHourlyRun)
{
// Do work here
}
}
* I'm not sure those cron expressions are correct

How to test/run azure times function locally

I have a solution in Visual Studio 2019, I added a new project of type "Azure functions". I have a function in that project that runs on a timer trigger.
I want to run that function only once during debug, is there a way to do that without fiddling with the timer settings so that it will only start, like, 10 seconds after I start debugging?
The function does not have any endpoints and it's not being called by anything, its point is to run on a schedule.
If I were to start debugging and set the timer to run it every X, but I want to run it explicitly only one time while debugging.
You can use the RunOnStartup option inside the [TimerTrigger] attribute. For example:
public static void Run(
[TimerTrigger("0 */5 * * * *", RunOnStartup = true)]TimerInfo myTimer,
ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
}
You can make it debug-only by using preprocessor directives:
public static void Run([TimerTrigger("0 */5 * * * *",
#if DEBUG
RunOnStartup = true
#endif
)]TimerInfo myTimer, ILogger log)
{
log.LogInformation($"C# Timer trigger function executed at: {DateTime.Now}");
}
You can execute timer triggered functions by sending a request to its admin url:
http://localhost:<your port>/admin/functions/<your function name>
Example POST:
POST /admin/functions/<function name> HTTP/1.1
Host: localhost:5800
x-functions-key: <your function key>
Content-Type: application/json
{}

How to create recurring Hangfire job every 10 minutes for only 24 hours

When I have a new customer signup that does not complete the process, I send them an email with next steps. I need to create a job that runs every 10 minutes for the first 24 hours after signup. After that time, there is another process that takes over. I schedule the job like this:
RecurringJob.AddOrUpdate(customerId, () => new NewCustomerProcess().checkNewCustomerStatus(customerId)), "*/10 * * * *");
If I add a job start time to the job class:
private DateTime _jobstart = DateTime.UtcNow;
Can I inspect that within the job to figure out when 24 hours has passed then remove the job?
RecurringJob.RemoveIfExists(customerId);
Does Hangfire re-instantiate the job class every time it runs?
if i understand your question correctly.
Hangfire does create a new instance of the job class every time.
So if I needed to solve this problem, I would pass in DateTime as a parameter every time the job is created:
RecurringJob.AddOrUpdate(customerId, () => new
NewCustomerProcess().checkNewCustomerStatus(customerId, DateTime.Now.AddDays(2))), "*/10 * * * *");
And then in the checkNewCustomerStatus compare with DateTime.Now
if (DateTime.Now > dateEnqueued)
{
//Job is complete
return;
}

Categories

Resources