SetTimeout in express callback - javascript

I am creating a route where a data attribute called "active" is being set to true, but after an hour is set to false. I am wondering if it is possible or bad practice to call a settimeout function in the express callback. Such as;
app.get("/test", (req, res) => {
//Some code
SetTimeout(func, 3600);
});
Is this bad for scalling, if this route was hit many times would it be very expensive? Thanks in advance.

If you store those values in a database, then you should not create a timer per entry in node that will reset this value. Especially it if it is a lang lasting timer, Session like/related data that should last longer then a few seconds should in general not be keept in the memory of the node process.
The more frequently your site is visited, the more likely it is that you have at least one timer running at any time. As soon as this is the case you are not able to restart the application without either loosing that timer. Or you need to wait until all timers are finished and while that don't accept any new ones.
And you cannot switch to clustered mode, because then if one user calls that route twice, it might end up in two different processes, each of those processes would not know of the timeouts the other process has set.
So a better idea is to add a timestamp into the database, and one cleanup timer responsible for all entries.

It seems you only need to set 1 timer. This assumes the 'hour' starts at the first request.
let timer = null
let data = true
app.get("/test", (req, res) => {
//Some code
if (!timer) {
timer = setTimeout(() => {data=false}, 3600);
}
});
Instead, for multiple users, you can avoid setting multiple timers by putting a timestamp in a hash and polling it per request or a separate interval timer.
// init
let timers = {}
// in request
if (!timers[user]) {
timers[user] = new Date().getTime() / 1000 + 3600
}
else if (timers[user] <= new Date().getTime() / 1000)
{
// update db, etc
}
// or poll for expirations in separate single timer routine
let now = new Date().getTime() / 1000
Object.keys(timers).forEach(user => {
if (timers[user] <= now) {
// update db, etc
}
})

Related

Call function on specific time on react js app?

On my react js SPA I need to call a function (that fetches an api to refresh access token) every 5 minutes. My first thought was on App.js:
useEffect(() => {
const interval = setInterval(() => {
// fetch API
}, 5*60*1000);
return () => {
clearInterval(interval);
};
}, []);
Problem is: say user refreshed page, or navigated to another page before the 5 minutes, then the action to fetch the API will be postponed for another 5 minutes, and so on.
What's the best approach to achieve what I'm expecting?
User logs in successfully
Set "timer" to fetch the API every 5 minutes regardless pages refreshes or user navigation.
Like a synchronous API fetch
I use node-schedule its a library you can use to schedule jobs, you might be able to schedule a job every 5 minutes of an hour so that even if the user refeshes it will still call the function at the 5th minute. For instance: I load the page at 12:53 and the job is scheduled for every 5th minute so it would call the function at 12:55. If I then refesh the page it will still schedule the job at 12:55. I'm not sure if this is what you're looking for but it might be an option.
For my program I have it setup so it calls a function every midnight.
const schedule = require('node-schedule');
schedule.scheduleJob('0 0 * * *', () => {
updateData()
})
You can find some examples here
you can save info about previous refresh in local storage, session storage and even cookies

Discord javascript l Deleting data from database after the time has expired

I made a premium membership system to my discord bot, but the time starts to be minus a certain time, so I want to delete the data from the database when the time I set with ms expires. I tried something like that but it didn't work
I save the data as follows;
Looks like you are setting the interval to an incredibly long time. It looks like you are storing the specific time you want the function to run. You'll probably want to do something like this:
let interval = sure - new Date();
if(interval < 0) { // this expiration date already passed
interval = 0;
}
setInterval(function() {
db.delete(` ... `);
db.delete(` ... `);
}, interval);
However! If you do all this multiple times (like inside the 'message' handler like you're doing right now), you're gonna have a memory leak. Make sure you are setting the intervals only once.
Also, if your program crashes, you'll have to set up all the intervals again at startup.
If I was making something like this, I would instead make a cron job to check only once per day to delete all the expired members, instead of using setIntervals.

Test if a function runs in the past minute or second javascript

I'm using socket.io with a node.js server in communication between clients, and in receiving message from one client I do some treatment in the callback and i have some code that run every time and some that must run once a minute to store data in a mysql database:
io.on('connection', function(socket) {
socket.on('createroom', function(room) {
socket.on('values', function(values) {
treatment done each time with values;
treatment must be done once a minute with values;
}
}
}
How I can test if a function or some code has run in the past minute.
You can record as a socket property, when you last processed this event and just check that time:
io.on('connection', function(socket) {
// initialize lastProcessed time to a long time ago (haven't done it yet)
socket.lastProcessed = 0;
socket.on('createroom', function(room) {
// there's a problem here because you will create duplicate event handlers
// for the values message
socket.on('values', function(values) {
treatment done each time with values;
if (Date.now() - socket.lastProcessed > (1000 * 60)) {
treatment must be done once a minute with values;
// update time we last processed it
socket.lastProcessed = Date.now();
}
});
});
});
FYI, you have another problem here that every time you get the createroom event you are adding another listener for the values message. You will end up with duplicate handlers for that message which is a problem. Since you don't explain the overall logic here, I'm not quite sure what solution to that would be best.
Possible solutions. Assign the values event handler at the same scope as you assign the createroom event handler or remove the values event handler after it occurs.

Clearing timeouts for one item in array - javascript

Say I have an messaging service that schedules messages to friends,
And a user uploads their friends, along with when they want to send them
But say 10000 milliseconds later after scheduling, the uploader wants to take bob out of the (for) loop. How do I take bob out, without canceling scheduler. Or is there a better way to do this? (Its on a node server)
var friends = [‘John’, ‘bob’, ‘billy’, ‘dan’];
for (i in friends) {
setTimeout(function(){
sendMessage(friend[i])
},3000000)
}
I feel like there is a much better way to do this but have not found anything
Thanks, new to js and appreciate the help!
setTimeout returns an object. Store that somewhere, and then call clearTimeout with that object tif you want to do so, as described here:
https://stackoverflow.com/a/6394645/1384352
The way you have your code, all the timeouts will expire at the same time.
Instead you could only initiate the next timeout when the current one finishes. In the following demo 'Billy' is removed while the messages are being sent with an interval of 1 second. And indeed, Billy gets no message:
var friends = ['John', 'Bob', 'Billy', 'Dan'];
(function loop(i) {
setTimeout(function(){
if (i >= friends.length) return; // all done
sendMessage(friends[i]);
loop(i+1); // next
}, 1000);
})(0); // call the function with index 0
function sendMessage(friend) { // mock
console.log('send message to ' + friend);
}
// now remove 'Billy' after 2.5 second
setTimeout(function () {
console.log('remove ' + friends[2]);
friends.splice(2, 1);
}, 2500);
One option could be that you add flag if user should be removed from the recipients and if flag is on you skip sending to that person. Then later on clean marked users when you can. e.g.
if (!friends[i].isRemoved) {
setTimout.....
}
Other option would be that you define individual timers for each friend and then you can cancel who ever you want.

Will using setTimeout ensure something executes in NodeJS?

I'm creating a REST backend using ExpressJS. A part of the backend allows users to upload file assets, which should only exist for 10 minutes.
It safe to use setTimeout, to delete the file after 10 minutes, or are there better ways of doing this in NodeJS? How can I ensure the file is deleted? Here is my current solution:
router.post('/upload', fileUpload.single('asset'), (req, res) => {
// Do something with the file
res.status(201).end();
setTimeout(() => {
// Delete the file
}, 600000);
});
Your approach is not going to scale, as it will potentially create a huge number of delayed methods. Better way is to store the information about the file into some associative array (object) such as :
{ "path":"date_uploaded" }
And to check every, say, XX seconds if there is anything that needs deleting with setInterval(). I.e. go through the whole structure and see if anythign was created more then 10 minutes ago. For all such elements you delete the file and remove it from the array.
var pending = {};
router.post('/upload', fileUpload.single('asset'), (req, res) => {
// Do something with the file
pending[file_name] = (new Date()).getTime();
res.status(201).end();
});
setInterval(
function(){
// check each element of pending and see if it needs to be deleted
}, 30000);

Categories

Resources