I am trying to create a windows service that executes twice a day.
and I was successfully able to create it using two triggers added to a single job.
var job = JobBuilder.Create<Job>().StoreDurably().WithIdentity("Report_Name", "Report_Group").Build();
scheduler.AddJob(job, true);
var trigger_1 = TriggerBuilder.Create()
.WithIdentity("Report_Name_1", "Report_Group_A")
.StartNow()
.WithCronSchedule(string.Format("0 {0} {1} ? * *", Utility.Schedule_StartTime_1.Minute, Utility.Schedule_StartTime_1.Hour)) //0 Min hour
.ForJob(job)
.Build();
var trigger_2 = TriggerBuilder.Create()
.WithIdentity("Report_Name_2", "Report_Group_B")
.StartNow()
.WithCronSchedule(string.Format("0 {0} {1} ? * *", Utility.Schedule_StartTime_2.Minute, Utility.Schedule_StartTime_2.Hour)) //0 Min hour
.ForJob(job)
.Build();
scheduler.ScheduleJob(trigger_1);
scheduler.ScheduleJob(trigger_2);
scheduler.Start();
Can I use a single trigger to add multiple cron schedules
No, the trigger can have only one schedule.
One of the main reason why this is done is to prevent a situation when it is not clear for scheduler how to resolve competition between
conditions.
Imagine you have a job with 2 intersected schedules: let's say you want to run the job every 15 mins and every hour, and it takes up to 10 mins to execute it. In this case, you would need to specify how you want to handle scenarios, when
a job is executing, but scheduler fires new execution.
a job should be fired by both schedules
To allow handling such cases, the trigger has attributes like Priority and Misfire Instructions.
Related
Every hour, new data will be loaded in a table. As soon as that is ready I want to call a stored procedure.
Is it possible with Snowflake Tasks and Streams to schedule that starting every hour on the hour, check every minute if the table has new data and if it does, call a stored procedure and stop checking every minute?
At first I thougt about having 1 task with an hourly schedule. The next task would be scheduled every minute and have the hourly task as its predecessor. Unfortunately it is not possible for a task to have both a predecessor and a schedule. What would be a way to create this kind of scheduling?
For example
CREATE OR REPLACE TASK tsk_X_X_1
WAREHOUSE = X
SCHEDULE = 'USING CRON 0 1 * * * UTC'
AS INSERT INTO XX.Test SELECT 'hourly', sysdate()
;
CREATE OR REPLACE TASK tsk_X_X_2
WAREHOUSE = X
SCHEDULE = '5 minutes'
AFTER TASK tsk_X_X_1
As INSERT INTO XX.Testing SELECT '5min', sysdate()
;
Error: Task TSK_X_X_2 cannot have both a schedule and a predecessor.
I'm creating an API that runs a function once every 30 seconds on demand from the client. The problem is that using Cron and Node-schedule execute all the jobs at the same time every 30 seconds regardless of the time the request came. E.g every xx:00 and xx:30 xx+1:00. The behavior that I'm looking for is to execute it with an interval depending on the request time, so if it came at xx:05 then it will execute it at xx:35 xx+1:05 and so on.
the function I'm using is :
const schedule = require('node-schedule');
schedule.scheduleJob(jobID, "*/30 * * * * *",()=> {JobFunction(jobID)})
This question is in continuation with this thread Repeatable jobs not getting triggered at given cron timing in Bull
I am also facing the same problem. How should I specify the timezone? I tried to specify as
repeat: { cron: '* 7 14 * * *', tz: 'Europe/Berlin'}
Meaning trigger the job at 14:07 German time zone. Though the job is listed in the queue, but the job is not triggered.
I also tried repeat:
{
cron: '* 50 15 * * *',
offset: datetime.getTimezoneOffset(),
tz: 'Europe/Berlin'
}
I finally figured out the solution.
One thing to note is that I had not initialized a Queuescheduler instance. Ofcourse timezone also plays a crucial role. But without a Queuescheduler instance (which has the same name as the Queue), the jobs doesnt get added into the queue. The Queuescheduler instance acts as a book keeper. Also take care about one more important parameter "limit". If you dont set the limit to 1, then the job which is scheduled at a particular time will get triggered unlimited number of times.
For example: To run a job at german time 22:30 every day the configuration would look like:
repeat: {
cron: '* 30 22 * * *',
offset: datetime.getTimezoneOffset(),
tz: 'Europe/Berlin',
limit: 1
}
Reference: https://docs.bullmq.io/guide/queuescheduler In this above link, the documentation clearly mentions that the queuescheduler instance does the book keeping of the jobs.
In this link - https://docs.bullmq.io/guide/jobs/repeatable, the documentation specifically warns us to ensure that we instantiate a Queuescheduler instance.
You need to manage repeatable queues with the help of QueueSchedular. QueueSchedular takes the queue name as first parameter and connection as second. The code will be as following:
const queueSchedular = new QueueSchedular(yourQueue.name, { connection });
I have a MySQL table tasks. In tasks, we can create a normal task or a recurring task that will automatically create a new task in the MySQL tasks table and send an email notification to the user that a task has been created. After a lot of research, I found out that you can do it in four methods
MySQL events
Kue, bull, agenda(node.js scheduling libraries)
Using a cron job to monitor every day for tasks
the recurring tasks would be repeated over weekly, daily, monthly, and yearly.
We must put an option to remove the recurring event at any time. What would be a nice and clean solution?
As you've identified there are a number of ways of going about this, here's how I would do it but I'm making a number of assumptions such as how many tasks you're likely to have and how flexible the system is going forward.
If you're unlikely to change the task time options (daily, weekly, monthly, yearly). Each task would have the following fields last_run_date and next_run_date. Every time a task is run I would update these fields and create an entry in a log table such as task_run_log which will also store the date/time the task was run at.
I would then have a cron job which fires a HTTP message to a nodejs service. This web service would look through the table of tasks, find which ones need to be executed for that day and would dispatch a message for each task into some sort of a queue (AWS SQS, GCP Pub/Sub, Apache Kafka, etc). Each message in the queue would represent a single task that needs to be carried out, workers can subscribe to this queue and process the task themselves. Once a worker has processed a job it would then make the log entry and update the last_run_date and next_run_date fields. If a task fails it'll add it into move that message into an error queue and will log a failed task in the task log.
This system would be robust as any failed jobs would exist as failed jobs in your database and would appear in an error queue (which you can either drain to remove the failed jobs, or you can replay them into the normal queue when the worker is fixed). It would also scale to many tasks that have to happen each day as you can scale up your workers. You also won't be flooding cron, your cron job will just send a single HTTP request each day to your HTTP service which kicks off the processing.
You can also setup alerts based on whether the cron job runs or not to make sure the process gets kicked off properly.
I had to do something very similar, you can use the npm module node-schedule
Node scheduler has many features. You can first create your rule setup, which determines when it runs and then schedules the job, which is where determine what the job performs and activates it, I have an example below from my code which sets a job to run at midnight every day.
var rule = new schedule.RecurrenceRule();
rule.dayOfWeek = [0, new schedule.Range(1, 6)];
var j = schedule.scheduleJob(rule, function(){
sqlUpdate(server);
});
This may not exactly fit all of your requirements alone but there are other features and setups you can do.
For example you can cancel any job with the cancel function
j.cancel()
You can also set start times and end times like so as shown in the npm page
let startTime = new Date(Date.now() + 5000);
let endTime = new Date(startTime.getTime() + 5000);
var j = schedule.scheduleJob({ start: startTime, end: endTime, rule: '*/1 * * * * *' }, function(){
console.log('Time for tea!');
});
There are also other options for scheduling the date and time as this also follows the cron format. Meaning you can set dynamic times
var j = schedule.scheduleJob('42 * * * *', function(){
console.log();
});
As such this would allow node.js to handle everything you need. You would likely need to set up a system to keep track of the scheduled jobs (var j) But it would allow you to cancel it and schedule it to your desire.
It additionally can allow you to reschedule, retrieve the next scheduled event and you can have multiple date formats.
If you need to persist the jobs after the process is turned of and on or reset you will need to save the details of the job, a MySQL database would make sense here, and upon startup, the code could make a quick pull and restart all of the created tasks based on the data from the database. And when you cancel a job you just delete it from the database. It should be noted the process needs to be on for this to work, a job will not run if the process is turned off
I wonder if it is possible to write an cron expression with several conditions:
Job should be run with given interval in minutes. For example with interval 42 minutes the fire times would be 10:00, 10:42, 11:24, 12:06 and etc.
If the current minute does not end with 0 (e.g. 10:28,10:29), then cron first fire time should be 10:30. So it means that first fire time should have "round" minutes.
I hope that you understand these conditions. Is it possible to describe them with quartz cron?
You can use job trigger like described below in Quartz.net 3.0:
var jobTrigger = TriggerBuilder.Create()
.StartNow()
.WithSimpleSchedule(s => s
.WithIntervalInMinutes(42)
.RepeatForever())
.Build();
And you can restart app at first round time, so it will fire first time at the same time only.
I usually use http://www.cronmaker.com/ to generate my cron expressions. And if you try the every 42 mins option you'll get the following expression: " 0 0/42 * 1/1 * ? *". As for the "round" minutes thing, you can try this when building your trigger:
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity(JobTrigger, JobGroup)
.WithCronSchedule(CroneExpression)
.StartAt(new DateTimeOffset(DateTime.Now,
TimeSpan.FromMinutes(DateTime.Now.Minute % 10)))
.Build();
It is not possible, see for explanation and similar issue: Quartz.net - Repeat on day n, of every m months?
it is also not possible by Cron expressions. To do this, you would need to apply some complex logic, use some operator that is not present in evaluators. Why do you need this? Would you like to combine those 2 requirements and create single complex pattern?