Cron is not firing on specific schedule - node.js

I want to run a cron job on a specific date of every month in node js.I am using a npm module named 'Cron' but the function is not firing on the specific date.Here is the code I am using
var CronJob = require('cron').CronJob;
new CronJob('0 0 0 21 * *', function () {
// this code run will on the 21st of every month
}, null, true, 'America/Los_Angeles');

Your cron pattern seems right but you can also try removing first 0 , beacuse second is not important in your case .I think problem is about your timezone value. Probably, your timezone is not America/Los_Angeles try to change it.
To fin your current timezone value check this site : http://momentjs.com/timezone/

Related

Checking the last time a request has been made, deleting stuff from database if the time exceeds a minute

I'm trying to make a timer that would check when the last request to a specific path was made and if the last request was made more than a minute ago, I want the script to delete a document from a mongodb database.
I've tried to achieve this with sessions, but I haven't been successful doing so. I've also tried to save the current time to the DB with the request and then checking it, but I don't know how to make the timer "run in the background", if that's even possible. I also want the timer to run per every ID (the ID is included in a table with the request)
Using a TTL index may help you. It would allow you to set an expiry date for documents when they are accessed, and MongoDB will take care of deleting them after the time is up.
Add a TTL index to your database:
db.entites.createIndex({ requestedAt: 1 }, { expireAfterSeconds: 60 });
When a request is made, update the documents you want to expire by setting the current date for the indexed field:
db.entites.updateMany({ requestId }, { $set: { requestedAt: new Date() } });
Any documents with the requestedAt field set, will be deleted 60 seconds after it's set timestamp.
Here is an option you can try:
For each request store some details in variable called last_request_time, e.g., timestamp. The last_request_time value gets updated for each request.
Run a cron job - the background job runs every 10 seconds (or 15, 20, or 30 secs). See node-cron.
The job:
Calculate difference of current_time and last_request_time
If difference is greater then 60 seconds:
Set the last_request_time value to null
Delete document from database

How `agenda.js` calculates timezone for `every()` operation

I am using agenda.js in my Node project, backed with a MongoDB database, to handle batch processes we need to run. This is working well. I do have a question about timezones, however. When I use the every() operation, it seems like it accepts the job name, and the schedule. So I have been seeding jobs to the database like so:
for (let job of dbJobs) {
await agenda.every(schedule, job.name);
}
Note that for the above, schedule is in cron format -- 00 05 * * 1-5.
This works. However, from what I can tell, every() doesn't accept an argument for repeatTimezone. So what does it do to calculate the timezone in those cases?
To clarify, when I look at the document in the database after the job has been added using every(), the repeatTimezone property exists, but its value is set to null.
Other agenda operations, like repeatEvery(), do accept an argument for timezone, like so:
job.repeatEvery('0 6 * * *', {
timezone: 'America/New_York'
});
Since I'm using every(), I have been managing this by first seeding the database using every(), and then running a Mongo updateMany() to add the timzeone explicitly to all jobs:
async function addTimezoneToJobs() {
try {
const db = await client.db(dbName);
await db.collection('batch_processes').updateMany({}, {
$set: {
repeatTimezone: 'America/New_York'
}
});
} catch (error) {
console.log(error);
}
}
But strangely enough, agenda seems to calculate the same time even when I don't explicitly add the repeatTimezone property value to the jobs as when I do.
What's happening here that I'm not understanding? How is the runtime calculated with every(), and is there a way to pass in timezone?
FYI: I am not in the same timezone as that which needs to be set in the db.
Your Question seems to be 2 part, I'm not exactly sure I'll be able to explain it very well but let me try
So, your first question
However, from what I can tell, every() doesn't accept an argument for Timezone
Well Technically you can add Timezone option to every() as well because what this method does is it calls job.repeatEvery internally and as you already know you can add timezone to that. To Support my answer, I found 2 evidence
From Documentation as every accepts 4 parameters
every(interval, name, [data], [options])
options is an optional argument that will be passed to job.repeatEvery. In order to use this argument, data must also be specified.
So you can technically pass timezone if you pass data as well
From SourceCode, here you can see they use job.repeatEvery(interval, options) internally.
Now, To your Second Question
what does it do to calculate the timezone in those cases?
Well They have a very unique yet required module named ComputeNextRunAt().
So I went through their Source Code and figured Out that this is to Compute when will be the next run for your job based on startingTime and Interval.
Your Code works because you have once (Initially) mentioned in your job to follow America/New_York timezone, so every next job interval is calculated based on that, that's the reason you don't need to specify it again.
So, If initially you haven't had specified the timezone attribute, you would have gotten your local Timezone but now you did so, it calculates the next interval based on that.

Single cron job run on several timezones node-cron

I have configured jobs with node-cron and yeah I love this node module to schedule job in node.
Here I have requirement of sending push notification to users which are located in different timezone.I want to send notification to them on specific time.
Let's say I am sending notification at 9 PM so in all listed timezone cron job will trigger at 9 PM.
var CronJob = require('cron').CronJob;
var job = new CronJob('00 30 11 * * 1-5', function() {
/*
* Runs every weekday (Monday through Friday)
* at 11:30:00 AM. It does not run on Saturday
* or Sunday.
*/
}, function () {
/* This function is executed when the job stops */
},
true, /* Start the job right now */
timeZone /* Time zone of this job. */
);
I know all this and I am doing same for one timezone as mentioned in there doc.
timeZone - [OPTIONAL] - Specify the timezone for the execution. This
will modify the actual time relative to your timezone.
But Can I specify multiple timezone here in timezone attribute?
If somebody aware of some other node module can achieve this then let me know?
NOTE : I already know I can configured multiple configuration here for each timezone but what if there are dynamic list.
I don't know of a way to send a list of timezones to the CRON job but you could change the logic in the method that runs inside the cron job.
You could do this :
run the job every half hour
if it's a day you want it to run on
select users where (convert current GMT time to user timezone - if the db can do this) > 11:30 AM in their timezone && hasn't sent a notification yet
send notifications to the returned users.
You might have already gone this route ... just throwing in my 2c
HTH

How to run cron trigger immediately?

What i should do to run CRON trigger to run now once and follow the expression for Example
trigger that simply fires every 5 minutes.
I have gone through the below post
https://groups.google.com/forum/#!topic/quartznet/GAv10E4TJ50
If you want to make sure your job is run immediately you can set start
time to one day before DateTime.Now, so you change your code to:
CronTrigger trigger = new CronTrigger("trig", "grp", "job", "grp",
DateTime.Now.AddDays(-1), null, "0 0 0 * * ?");
But does the above work for any scenario. like
0 0/5 14 * * ? Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day (if current time is 2:15pm)
Thanks,
Kusuma
What about creating a CRON trigger with a temporary schedule to "trigger the job now" (e.g. 0 * * * * ?) and implementing a JobListener that would update the CRON trigger's expression once the job has been executed for the first time? You can use, for example, a job data map parameter to distinguish the first and subsequent executions in the listener.
If you do not insist that it must always be the same CRON trigger that "executes the job now" and then continues to execute it regularly, then you can use one of the triggerJob methods that both create a temporary on-off SimpleTrigger that is used to execute the job now.
The time at which the trigger's scheduling should start. May or may not be the first actual fire time of the trigger, depending upon the type of trigger and the settings of the other properties of the trigger. However the first actual first time will not be before this date.
So i could able to run immediately by setStartTime

Cron Expression to not run on a particular date

I have a cron job that Runs using Quartz.NET.
<cron-expression>0 5 * * * ?</cron-expression>
It runs every 5 minutes as you can see above, but I want it to not run from 5pm on 30/Dec/2013 to 7am on 01/Jan/2014..
Is this possible does anyone know?
Thanks
Neil
Exclusion are most easily made with calendars. With calendar you can exclude a set of days, weekdays, time of days or a cron expression from schedule. Calendar is checked always checked after fire time has been determined (is this OK to run?).
You could either chain multiple calendars because you have nasty complexity of passing the year, multiple days and time range on top of that. More readable and understandable solution could be to implement your own fixed time range calendar (implementing ICalendar) that takes end and start time and excludes them.
You could naturally also make your first cron trigger end at 2013-12-30 17:00 and add a new trigger that starts at 2014-01-01 07:00.
Here's a trivial sample utilizing CronCalendar:
var calendar = new CronCalendar("0 * 1 * * ?");
scheduler.AddCalendar("myCalendar", calendar, replace: false, updateTriggers: false);
var trigger = TriggerBuilder.Create()
.WithCronSchedule("0 5 * * * ?")
.ModifiedByCalendar("myCalendar")
.Build();
scheduler.ScheduleJob(trigger);

Resources