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

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;
}

Related

Incorrect job interval when using HangFire

I have 2 simple jobers GetMenuJober and GetOrdersJober. All they do is printing message in console, RunJob method is similar in both classes:
public async Task RunJob()
{
Console.WriteLine($"{this.GetType().Name} has been started.");
}
I planned to start these workers in 5 seconds:
RecurringJob.AddOrUpdate<GetOrdersJober>(x => x.RunJob(), "0/5 * * * * *");
RecurringJob.AddOrUpdate<GetMenuJober>(x => x.RunJob(), "0/5 * * * * *");
And expected to see something like this in the console:
GetOrdersJober has been started.
GetMenuJober has been started.
GetOrdersJober has been started.
GetMenuJober has been started.
GetOrdersJober has been started.
GetMenuJober has been started.
The intervals between the launches of both are different, while they are not equal to 5 seconds, sometimes 30, sometimes more than a minute. Jobs run completely different. What did I miss ?
Moreover, even if I set cron expression as Cron.Minutely both jobs will run in absolutely random interval.

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 can I create a one time pipeline run with a long delay in c# data factory

I need to trigger a pipeline I have built inside of my azure data factory with certain parameters based off of a file I have stored in a database. My problem is that I need to schedule this pipeline to trigger ONCE after a certain amount of time( will usually be hours). This is needed for scheduling and I can't do it event driven. I am using the .NET SDK
I have already created a connection to my data factory and created a schedule trigger. My problem is that a schedule trigger doesn't allow me to trigger one time and then stopping. It requires intervals and a stop date, I tried to set the stop date the same as the start date but it gives me the error of "interval cannot exceed end date".
for (int x = 0; x < intervals.Count; x++)
{
// Create a schedule trigger
string triggerName = location + deliveryDate+x;
ScheduleTrigger myTrigger = new ScheduleTrigger()
{
Pipelines = new List<TriggerPipelineReference>()
{
// Associate the Adfv2QuickStartPipeline pipeline with the trigger
new TriggerPipelineReference()
{
PipelineReference = new PipelineReference(pipelineName),
Parameters = pipelineParameters,
}
},
Recurrence = new ScheduleTriggerRecurrence()
{
StartTime = intervals[x],
TimeZone = "UTC",
EndTime = intervals[x],
Frequency = RecurrenceFrequency.Day
}
};
// Now, create the trigger by invoking the CreateOrUpdate method
triggerResources.Add(triggerName,new TriggerResource()
{
Properties = myTrigger
});
}
I cannot do a pipeline run because there is not way for me to do a run after a certain delay (like 2 hours) if this was possible I would just create a delayed pipeline run...I have tried everything like leaving the frequency blank, changing it to every possibility, and even using different trigger classes like tumbling and event.
There is a simple, crude solution. Create a new pipeline with a parameter of integer type. The first activity in the pipeline will be a Wait Activity. Use the parameter to set how long the Wait Activity should last. The Second activity in the pipeline will be an Execute Pipeline Activity, which depends on the Wait Activity, and will trigger the pipeline you really want to run.
This solution lets you choose how long to wait, then execute the real pipeline you want to run. The Wait Activity is in seconds, I think, so you will need to do some arithmetic. However since you can trigger manually, it shouldn't be a problem.

Why Quarz.net job firing multipule time for same trigger instance c#

I am trying to build triggers for a job in Quarz.net based on config settings something like
var keysArray = [1,2]
keysArray.ForEach(key =>
{
//schedule will be unique for a key
var schedule = AppConfig.Get($"CronJobs.{key}.TimeSheetAutoSubmit.Schedule.QuarzExpression") ?? "0 30 23 * * ?";
var timeZoneId = AppConfig.Get($"CronJobs.{key}.TimeSheetAutoSubmit.TimeZoneId") ?? "India Standard Time";
var trigger = TriggerBuilder.Create()
.ForJob(jobDetail)
.WithCronSchedule(schedule, x => x
.InTimeZone(TimeZoneInfo.FindSystemTimeZoneById(timeZoneId)))
.WithIdentity($"TimeSheetAutoSubmitTrigger_{key}")
.WithDescription($"ConfigKey_{key}")
.StartNow()
.Build();
Scheduler.ScheduleJob(jobDetail, trigger);
});
Works fine but problem is trigger is firing multiple times when i check the logs
2017-03-16 12:04:12,247 [DefaultQuartzScheduler_Worker-1] INFO UnitedLex.Services.JobHandlers.timesheetautosubmit - job started
2017-03-16 12:04:13,510 [DefaultQuartzScheduler_Worker-2] INFO UnitedLex.Services.JobHandlers.timesheetautosubmit - job started
2017-03-16 12:04:13,710 [DefaultQuartzScheduler_Worker-2] INFO UnitedLex.Services.JobHandlers.timesheetautosubmit - job started
Don't know what i am doing wrong here....
I may be wrong but I think it's normal because your job builder/scheduler is inside a foreach, the amount of times it gets fired is equal to the length of your array.
If you want your jobs to not run in concurrent mode use this attribute [DisallowConcurrentExecution] on your job definition.
This way the next job trigger will wait for the current running job to finish.

How do I create a process that checks date time and performs action when elapsed time passed?

in my dll I'm serializing an object that I need to expire, and regenerate when x amount of days have passed.
How can I do this in a way that doesn't require the calling application to restart every day (in order to initiate the check for date time in my dll)?
using .net 3.5
private void updatePersistableItems()
{
if (!File.Exists(Items_FILENAME) && PersistableItems != null) //create new
{
_serializer.SerializeObject<PersistableObject>(Items_FILENAME, PersistableItems);
}
else //check if expired and replace, or update if not expired
{
PersistableObject ItemsFromStorage = new PersistableObject();
ItemsFromStorage = _serializer.DeSerializeObject<PersistableObject>(Items_FILENAME);
TimeSpan ts = DateTime.Now - ItemsFromStorage.DateItemsInitialized;
if (ts.TotalDays < this.DaysToPersistItems) //use stored Items
Items = ItemsFromStorage.Items;
}
}
Use a Timer to periodically call your function that does the checking: http://msdn.microsoft.com/en-us/library/system.timers.timer(v=vs.110).aspx
You can start new Thread with while loop. Once executed on start of the application the thread can check the time amount left till content expiry, and go to sleep for the rest of the time. Once waked up after sleep, refresh content, calculate time amount left to sleep .... : )
Sounds like a job for a the task scheduler which can be controlled via c# this wrapper. Using this you can schedule the update to get run even if your application is not running all the time.

Categories

Resources