I am trying to do a cron job but it only works if the time specified is every second or every minute. However, If I try to specify a time (day, month , hour and minute) I am unable to get a response.
CronService.js file :
var CronJob = require('cron').CronJob;
module.exports = {
startJob : function(time) {
new CronJob(time, function() {
console.log('test');
}, null, true,'Asia/Singapore');
}
}
some controller.js file :
startCronService : function(req, res, next) {
var time = '12 15 29 8 *';
CronService.startJob(time);
},
I tried changing the timezones to 'America/New_York' and adjust my time as well. but the cron job will never respond.
Am I doing something wrong with the time syntax?
After trying multiple things, I found out that you must provide the name of the month rather than the number (Jan,Feb) etc. Although, the npm documentation mentioned that we are able to use both, but that is false unfortunately.
Related
I am using #nestjs/schedule for scheduling tasks. Sample code for scheduling are as follows
async scheduleCron(cronId: any, day: any){
let cronTime = '0 0 '+day+' * *';
const job = new CronJob('* * * * *', () => {
this.postOrder();
});
this.schedulerRegistry.addCronJob(cronId, job);
job.start();
}
Here cronId is my custom Id which I passed to identify between different crons. Now when postOrder is called by a specific cronjob I want to access cronId of cronjob so that I know which cronjob had executed and based on that I can make appropriate db queries.
Is there a way I can access id ?.
From documentation what I understand is that you need to pass id to fetch details and not the other way around.
Any clue or alternative way to solve this issue would be really appreciated.
Do you mean accessing the list of the job like this?
this.schedulerRegistry.getCronJobs().forEach((job) => {
job.stop();
})
I am trying to make a discord bot that will scrape a group google calendar and remind people of upcoming events. I can get the calendar data no problem. Thing thing I don't understand is how to send a scheduled message on a discord server via discord js. This won't be a set time because it will change based on the start time of the calendar event. I'm trying to read the documentation for the GuildScheduledEvent here. But, I can't seem to figure it out/how to implement it.
I've already tried doing it from a cron task but that won't work because the event time is subject to change.
What I have so far is just a bot that will send messages when I run the script. I would really like to have it be automatic via a scheduled event.
let upcomingEvents = []; //array of calendar events
const gcpClient = authorize().then(listEvents); //getting the calendar data
const client = new Client({ intents: [GatewayIntentBits.Guilds]});
client.once(Events.ClientReady, c => {
console.log('Ready! Logged in as ', c.user.tag);
const channel = client.channels.cache.get('1049384497017266228');
upcomingEvents.forEach(element => {
channel.send(`${element.title} on ${element.readabledate}`);
});
})
client.login(TOKEN);
Again, I don't really know how to implement the Scheduled event logic.
Any help would be greatly appreciated.
As far as I understand the class ScheduledEvent doesn't represent what you need, it's for guild events like the ones explained here: https://support.discord.com/hc/en-us/articles/4409494125719-Scheduled-Events
What you need is the 'cron'-package from npm (https://www.npmjs.com/package/cron).
I modified your code to schedule a message for each upcomingEvents entry.
var CronJob = require('cron').CronJob;
let upcomingEvents = []; //array of calendar events
const gcpClient = authorize().then(listEvents);
const channel = client.channels.cache.get('1049384497017266228');
// method to convert date values to cron expressions
const dateToCron = (date) => {
const minutes = date.getMinutes();
const hours = date.getHours();
const days = date.getDate();
const months = date.getMonth() + 1;
const dayOfWeek = date.getDay();
return `${minutes} ${hours} ${days} ${months} ${dayOfWeek}`;
};
function scheduleMessage(cronExpression, msgToSend) {
var job = new CronJob(
cronExpression, // cron expression that describes when the function below is executed
function() {
channel.send(msgToSend); //insert here what you want to do at the given time
},
null,
true,
'America/Los_Angeles' //insert your server time zone here
);
}
client.once(Events.ClientReady, c => {
console.log('Ready! Logged in as ', c.user.tag);
upcomingEvents.forEach(element => { scheduleMessage(element.title, element.readabledate) });
});
client.login(TOKEN);
To get the correct cron expressions for each date value you need to convert it first, as answered in this post: https://stackoverflow.com/a/67759706/11884183
You might need to adjust some things like time zone and cronjob behavior.
If you want to keep the created cronjobs up to date you can delete them and recreate them in intervals
I am using node bull for scheduling. Now for my jobs i pass a cron time to it (which is a specific time and a date). Now since i have provided a strict cron then it must run for only one time or even if it run second time then it must be removed from the queue (i have provided removeOnComplete: true).
But still it doesn't get removed and it runs again and my queue process this job again. So i want to stop this.
My add job function: (data is my job data, timings is my cron timing)
public async addJob(data: any, timings: any, jobId: any) {
console.log('adding job');
console.log(timings);
const job = await this.videoQueue.add(
{data: data},
{
repeat: {
cron: timings,
},
jobId: jobId,
removeOnComplete: true,
},
);
return job;
}
My process function:
this.videoQueue.process(async (job: any) => {
// processing function for my job.
});
I am new node and node bull. Maybe i am making a mistake but i am not able to debug it.
Thanks.
I can suggest you use node-schedule package to schedule with cron time. It's very easy to use actually
const schedule = require('node-schedule');
const job = schedule.scheduleJob('* * * * *', function(){
console.log('Job runned.');
job.cancel();
});
Suppose I have this code running on 3 different servers and every server is using a single database.
setInterval(function(){
if(userArray) {
var report = mongoose.connection.db.collection('report');
report.insert({datenow:new Date(),userlist:userArray},function(err,doc) {
if(err) throw err;
});
}
},600000);
So, this piece of code is running every 10 minutes on every server but I want only one of them to insert the data into the database. Since the data is same it is getting inserted 3 times.
How do I check if the data is already inserted into the database by any one of the servers.
I tried making an incrementing count variable and insert it into the database and use it as a unique ID to check if it exists in the database. If it exists then I won't insert the data. But what if I have to restart the server for some reason, then the count will be reset to its initial value and this doesn't seem a viable solution.
So, how do I approach this problem? I am guessing I have to compare time somehow?
IMO, you should use a Cron expression instead of interval and use the execution time as primary key of your report when you perform the insertion in the database.
Explanation
Cron expression can garantee that the execution of your script will occur at an accurate time. If you use this Cron expression : 00 */10 * * * * (every 10 minutes), your script will execute at exactly 11:00:00, 11:10:00, 11:20:00, so on.. for every server you have.
So you can use this execution time as key for your reports and it will prevent multiple insertion of the same report.
Libs
You can use this lib to use Cron with Node.js : node-cron
Example
var CronJob = require('cron').CronJob;
new CronJob('* * * * * *', function() {
console.log('You will see this message every second');
}, null, true, 'America/Los_Angeles');
I hope this will help you.
So I had to end up comparing timestamps and checking it anything is inserted in the last 10 minutes. This is the solution I came up with.
setInterval(function(){
var currDate = new Date().getTime();
if(keyPairNameArray) {
var overallreport = mongoose.connection.db.collection('overallreport');
overallreport.find({}).sort({_id:-1}).limit(1).toArray(function(err, res){
if(res.length > 0){
var dbDate = new Date(res[0].datenow).getTime();
var diffDate = currDate - dbDate;
if(diffDate < 600000){
} else {
overallreport.insert({datenow:new Date(),userlist:keyPairNameArray},function(err,doc) {
if(err) throw err;
});
}
} else {
overallreport.insert({datenow:new Date(),userlist:keyPairNameArray},function(err,doc) {
if(err) throw err;
});
}
});
}
},610000);
I'm trying to schedule several cron jobs to generate serial numbers for different entities within my web app. However I am running into this problem, when I'm looping each table, it says it has something to do with date.js. I'm not doing anything with a date object ? Not at this stage anyway. A couple of guesses is that the cron object is doing a date thing in its code and is referencing date.js. I'm using date.js to get access to things like ISO date.
for (t in config.generatorTables) {
console.log("t = " + config.generatorTables[t] + "\n\n");
var ts3 = azure.createTableService();
var jobSerialNumbers = new cronJob({
//cronTime: '*/' + rndNumber + ' * * * * *',
cronTime: '*/1 * * * * *',
onTick: function () {
//console.log(new Date() + " calling topUpSerialNumbers \n\n");
manageSerialNumbers.topUpSerialNumbers(config.generatorTables[t], function () { });
},
start: false,
timeZone: "America/Los_Angeles"
});
ts3.createTableIfNotExists(config.generatorTables[t], function (error) {
if (error === null) {
var query = azure.TableQuery
.select()
.from(config.generatorTables[t])
.where('PartitionKey eq ?', '0')
ts3.queryEntities(query, function (error, serialNumberEntities) {
if (error === null && serialNumberEntities.length == 0) {
manageSerialNumbers.generateNewNumbers(config.maxNumber, config.serialNumberSize, config.generatorTables[t], function () {
jobSerialNumbers.start();
});
}
else jobSerialNumbers.start();
});
}
});
}
And this is the error message I'm getting when I examine the server.js.logs\0.txt file:
C:\node\w\WebRole1\public\javascripts\date.js:56
onsole.log('isDST'); return this.toString().match(/(E|C|M|P)(S|D)T/)[2] == "D"
^
TypeError: Cannot read property '2' of null
at Date.isDST (C:\node\w\WebRole1\public\javascripts\date.js:56:110)
at Date.getTimezone (C:\node\w\WebRole1\public\javascripts\date.js:56:228)
at Object._getNextDateFrom (C:\node\w\WebRole1\node_modules\cron\lib\cron.js:88:30)
at Object.sendAt (C:\node\w\WebRole1\node_modules\cron\lib\cron.js:51:17)
at Object.getTimeout (C:\node\w\WebRole1\node_modules\cron\lib\cron.js:58:30)
at Object.start (C:\node\w\WebRole1\node_modules\cron\lib\cron.js:279:33)
at C:\node\w\WebRole1\server.js:169:46
at Object.generateNewNumbers (C:\node\w\WebRole1\utils\manageSerialNumbers.js:106:5)
at C:\node\w\WebRole1\server.js:168:45
at C:\node\w\WebRole1\node_modules\azure\lib\services\table\tableservice.js:485:7
I am using this line in my database.js file:
require('../public/javascripts/date');
is that correct that I only have to do this once, because date.js is global? I.e. it has a bunch of prototypes (extensions) for the inbuilt date object.
Within manageSerialNumbers.js I am just doing a callback, their is no code executing as I've commented it all out, but still receiving this error.
Any help or advice would be appreciated.
Ok I've commented out the date.js module and now I'm getting this error:
You specified a Timezone but have not included the time module. Timezone functionality is disabled. Please install the time module to use Timezones in your application.
When I examine the cron.js module it has this statement at the top:
var CronDate = Date;
try {
CronDate = require("time").Date;
} catch(e) {
//no time module...leave CronDate alone. :)
}
So this would conclude then that it does have something to do with the date.js module ?
Anyone see whats wrong.
cheers
I was using date.js for a while, and then realized that the Date object in Node.js/V8 already had ISO support, input and output, and Date.js only added a very specific edge case. What exactly do you need date.js for?
If you do need date.js...
is that correct that I only have to do this once, because date.js is global?
That's true as long as the code is running in the same process. I'm not familiar Node.js on Azure, or the library providing the cronJob method you're using, but perhaps it spawns a new process, which has its own V8 instance, and then you lose the Date object changes? (So require it again in that code.)