I have the problem that in the server the Crone Task is running X4 number of times for each scheduled interval, not only the logs are shown x4 but also the API is called 4 times.
const taskCron = nodeCron.schedule('*/1 * * * *', function () {
const timeZone = moment.tz('America/Mexico_City').format();
const currentDate = splitDate(timeZone);
const currentTime = splitTime(timeZone);
console.info(`EXECUTING CRON TASK ${currentDate} ${currentTime}`);
campaign.find(
{ hour_to_send: currentTime, date_to_send: { $gte: currentDate, $lte: currentDate}}
).exec().then(data => {
console.log('number of campaigns programmed: ' + data.length);
const campaignsMapped = data.map(campaign => {
return {
id: campaign._id
};
});
const secretBulk = 'secret-bulk';
const bodyRequest = {
campaignsList: campaignsMapped,
key: secretBulk
};
if (campaignsMapped.length > 0) {
axios.post(url_bulk, bodyRequest, {})
.then(data => {
console.info(data.status);
})
.catch(error => {
console.error(error.code);
});
}
}).catch(error => {console.log(error)});
function splitDate(date) {
return date.slice(0, 10);
}
function splitTime(date) {
return date.slice(11, 16) + ':00';
}
}, {scheduled: false});
taskCron.start();
Use the library node-cron npm
The server is derived from centos Oracle version, the program runs in a docker container official Node JS image version 10, docker Docker version 19.03.11, build 42e35e61f3, It is worth mentioning that on my local machine with windows 10 this behavior does not happen.
Related
I have a nestjs cron problem.
I called just one time a cron function but function running 6 times. My code is below.
#Cron(CronExpression.EVERY_MINUTE)
async watcher() {
const now = new Date();
const openTravelRequests = await this.getOpenTravelRequestsByDate(now);
if(openTravelRequests.length) {
openTravelRequests.map(async(otr) => {
await this.assignNewBoatToOpenTravelRequests(otr._id)
})
}
}
}
I have tried counter but not working.
I have a POST ENDPOINT in my API where i want to register all work journals a worker made.
export const registerPoint = async (req: Request, res: Response) => {
const user = res.locals.decoded;
const {id} = user;
const ponto = new Ponto;
ponto.datePoint = new Date();
ponto.user_id = id;
//this numPoint should restart every day for that user...
ponto.numPoint = 1;
res.json({ msg: "Register point Route", user, id });
return;
}
how can i control how many times this requisition was made by a worker?
I want to control the variable numPoint, when the user makes this requisition it should increase by 01 and then in the final of the day returns it to 0.
Anyone knows about a solution or about a npm package that can handle this?
EDIT: Im storing all the data with SEQUELIZE + MYSQL.
As a starting point you could use a simple database for storing the data such as https://www.npmjs.com/package/sqlite3 or MySQL.
Running jobs daily you could consider https://www.npmjs.com/package/node-cron , for example having a daily job (outside of an API call function);
var cron = require('node-cron');
cron.schedule('0 0 1 * *', () => {
console.log('running every minute to 1 from 5');
});
From what I understand, you need a logging/audit trail mechanism. Since you are using MySQL you can create a new table with columns like (datetime, user_id, action). Every time the user does any action, it will be logged here. Then you can easily find out the count by aggregation. You won't need to reset any count for any user, if data doesn't exist for a given date then it's count will be 0.
I've made a solution that it worked for what i want.
Here is the solution below:
export const registerPoint = async (req: Request, res: Response) => {
const decodedUser = res.locals.decoded;
const user = await User.findByPk(decodedUser.id);
const TODAY_START = new Date().setHours(0, 0, 0, 0);
const NOW = new Date();
const markedPointsOfDay = await Ponto.findAll({
where: {
datePoint: {
[Op.gt]: TODAY_START,
[Op.lt]: NOW
},
}
});
const markedPointsOfDayByUser = await Ponto.findAll({
where: {
datePoint: {
[Op.gt]: TODAY_START,
[Op.lt]: NOW
},
UserId: (user !== null) ? user.id : decodedUser.id
}
})
if (!markedPointsOfDay || markedPointsOfDay.length === 0) {
const ponto = new Ponto;
ponto.datePoint = new Date();
if (user) {
console.log(user)
ponto.UserId = user.id as number;
console.log(ponto.UserId);
}
if (markedPointsOfDayByUser) {
ponto.numPoint = markedPointsOfDayByUser.length + 1;
}
const newPoint = await ponto.save();
res.json({ msg: "Ponto registrado com sucesso", msg2: "Caiu no IF de quando nao encontrou ponto do DIA", newPoint })
return;
}
if (markedPointsOfDay) {
const ponto = new Ponto;
ponto.datePoint = new Date();
if (user) {
ponto.UserId = user.id as number;
}
if (markedPointsOfDayByUser) {
ponto.numPoint = markedPointsOfDayByUser.length + 1;
}
const newPoint = await ponto.save();
res.json({ msg: "ponto registrado", markedPoint: newPoint, markedPointsOfDayByUser });
return;
}
return;
}
Tags:
node-cron, ExpressJs, NodeJs, Replit, Uptimerobot
Situation:
Hey all!
I am trying to get my discord bot to send multiple messages every day on specific times.
I deployed my bot on Replit and use Uptimerobot to ping my app every 10 min to keep the bot live.
In my code I used node-cron shedules for each spicific time it should send a message:
imports
const express = require("express");
const router = express.Router();
const { Client, Intents, Guild } = require("discord.js");
const cron = require("node-cron");
const token = process.env['BOT_TOKEN']
const { promotions } = require("./promotions");
const { testServers } = require("./test-servers");
const { buildMessage } = require("./generateMessage");
Message generator
router.get("/", function(req, res, next) {
const client = new Client({
intents: [Intents.FLAGS.GUILDS],
allowedMentions: { parse: ["users", "roles"] }
});
const composeMessage = guilds => {
let thisGuild;
let discordChannel;
let role;
let holidays;
let start;
let end;
guilds.map((guild, key) => {
guild.channels.cache.map(channel => {
testServers.forEach((promo, index) => {
thisGuild = promo.guild_id;
discordChannel = promo.channel_id;
role = promo.role_id;
holidays = promo.holidays;
start = promo.start;
end = promo.end;
// All relevant promotions
if (discordChannel === channel.id.toString()) {
const notAHoliday = [];
const currentDate = new Date();
holidays.forEach(holiday => {
if (
currentDate >= holiday.start &&
currentDate.setUTCHours(23, 59, 59) <= holiday.end
) {
notAHoliday.push(false);
}
});
if (
notAHoliday.length === 0 &&
(currentDate >= promo.start &&
currentDate.setUTCHours(23, 59, 59) <= promo.end)
) {
const unfilteredMessage = buildMessage(role);
channel.send(unfilteredMessage);
}
}
});
});
});
};
When running the Bot
client.once("ready", () => {
console.log("READY!");
const guilds = client.guilds.cache.map(guild => guild);
cron.schedule("0 55 7 * * Mon,Tue,Wed,Thu,Fri", () => {
console.log("morning");
composeMessage(guilds);
});
cron.schedule("0 31 11 * * Mon,Tue,Wed,Thu,Fri", () => {
console.log("start lunch");
composeMessage(guilds);
});
cron.schedule("0 25 12 * * Mon,Tue,Wed,Thu,Fri", () => {
console.log("end lunch");
composeMessage(guilds);
});
cron.schedule("0 0 16 * * Mon,Tue,Wed,Thu,Fri", () => {
console.log("evening");
composeMessage(guilds);
});
});
client.login(token);
botStatus = "Active";
res.render('index', { status: botStatus, version: "1.0.0" })
});
module.exports = router;
Issue:
The timers work but every time it runs a schedule, I get back a bunch of messages (the longer between schedules, the more messages my bot sends)
I suspect that it has to do with the pinging and the schedules stocking those runs until the shedule runs active and releases it all..
But how should I fix this?
Thanks in advance!
the code i am running when using promise.all should run at about \8 the time when i am using regular "blocking" for, but the result is very similar not even half the time.
i have tried to run this 2 NODEJS programs in the same computer.
WHEN USING PROMISE.ALL
let user = { "name": "shay", "interests": ["category1", "category2", "category3", "category4", "category5", "category6", "category7", "category8", "category9", "category10"] }
let result = [];
let Companies = [];
for (i = 0; i < 3000000; i++) {
let company = { "name": "company" + i, "interest": "category" + (Math.floor(Math.random() * 10) + 1) };
Companies.push(company);
}
const successRate = () => {
return (Math.floor(Math.random() * 100) + 1) + "%"
}
const task = function (interest) {
return new Promise((resolve, reject) => {
Companies.forEach(company => {
if (company.interest == interest)
result.push({ "company": company.name, "interest": company.interest, "success": successRate() })
});
resolve('succeed!');
});
};
const run = async function () {
let tasks = user.interests.map(interest => {
return task(interest)
});
await Promise.all(tasks);
}
const start = Date.now();
run();
WHEN USING REGULAR FOR
let user = {"name":"shay","interests":["category1","category2","category3","category4","category5","category6","category7","category8","category9","category10"]}
let result =[];
let Companies = [];
for (i=0;i<3000000;i++)
{
let company = {"name":"company"+i,"interest":"category"+(Math.floor(Math.random() * 10) + 1)};
Companies.push(company);
}
const successRate=()=>{
return (Math.floor(Math.random() * 100) + 1)+"%"
}
const start = Date.now();
user.interests.forEach(interest => {
Companies.forEach(company => {
if (company.interest==interest)
result.push({"company":company.name,"interest":company.interest,"success":successRate()})
});
});
console.log("run time",Date.now()-start);
the promise.all total run time is 1314
the regular for total run time is 1430
Node.js follows a single threaded architecture, it doesn't create a new thread for a new promise - everything runs in the same thread. Asynchronous behaviour is achieved via event loop, underlying OS concurrency and libuv. If you're familiar with Nginx - it actually works pretty much the same way. So don't mix JavaScript's Promise<> with Java's Future<>.
On init of my application i start function with settings.
const schedule = require('node-schedule');
const monk = require('monk');
const db = monk(config.mdbConnect);
var TGusers = db.get('TG-users');
...
...
TGusers.find({'cron.status': true}, {chatid:1, cron: 1})
.then((users) => {
console.log('twise');
for(var i=0;i<users.length;i++){
cronbox[users[i]] = {};
cronbox[users[i]].reminder = schedule.scheduleJob('*/1 * * * *', function(chatid){
console.log('chatid = '+ chatid);
tg.api.sendMessage(chatid, '🐳 Nuclear launch detected! / ' +chatid,
{'parse_mode': 'Markdown'}
);
}.bind(null, users[i].chatid));
}
}).catch((err) => {
if(err) saveerr(err);
}).then(() => db.close())
And this Monk find finction fired twice. I got two "twice" in my console, and .. looks like two cron tasks... What I did wrong?