Let's say you have a parking meter app. User selects an amount of time and pays. 20 minutes before their time is up you want to send them a text via Twilio that their time is almost up. I'm not concerned about the payment or text part. What's the best way to do the timing aspect in Node that triggers the function that sends the text 20min before their time is up? Im aware of setTimeout, but is this a scalable method of handling this? IIRC, setTimeout doesn't execute at exactly the end of it's timer, but is dependant on when it can execute within the event loop. Let's assume you may need a couple hundred timers running at once and your server is realtively busy with other users triggering other callbacks and async functions. Also, the text doesn't necessarily have to be sent at exactly 20min before their time is up, a couple minutes margin of error would be acceptable. Thanks for any help!
Related
I'm trying to make a server for a role-based browser game, so what I did so far:
Once 2 players join the server, a room is created, then it starts its own timeout of let's say 10 seconds, once the timeout is done, it changes its state and reruns the timeout.
I'm afraid if I have many rooms that may impact the performance, so an idea came to my mind which is, create a setInterval that tick every second, and loop through all rooms to call an update, inside the room once update called, it will check last time it updated its state vs current time, if 10 seconds passed, it updates to the new start.
I'm afraid that with setInterval every second may be worse than the first idea, or the opposite?
It would be far more efficient to let each room have its own timer than to have one frequent setInterval() that has to loop through all the rooms.
Timers in nodejs are super efficient and can easily scale to zillions of timers. They are stored in a sorted linked list and only the head of the linked list is compared vs the current time in the event loop. All the rest of the timers in the linked list have no regular cost - they just sit in the linked list until they are finally at the head of the list. There is slightly more cost to adding a new sorted timer when the linked list is long, but that's probably better than having a single interval that spends a lot of time looping through rooms that haven't reached their timeout. The nodejs timer system is just a more efficient way to do that.
Can the execution of an expressJS method be delayed for 30 days or more just by using setTimeout ?
Let's say I want to create an endpoint /sendMessage that send a message to my other app after a timeout of 30 days. Will my expressJS method execution will last long time enough to fire this message after this delay ?
If your server runs continuously for 30 days or more, then setTimeout() will work for that. But, it is probably not smart to rely on that fact that your server never, ever has to restart.
There are 3rd party programs/modules designed explicitly for this. If you don't want to use one of them, then what I have done in the past is I write each future firing time into a JSON file and I set a timer for it with setTimeout(). If the timer successfully fires, then I remove that time from the JSON file.
So, at any point in time, the JSON file always contains a list of times in the future that I want timers to fire for. Any timer that fires is immediately removed from the JSON file.
Anytime my server starts up, I read the times from the JSON file and reconfigure the setTimeout() for each one.
This way, even if my server restarts, I won't lose any of the timers.
In case you were wondering, the way nodejs creates timers, it does not cost you anything to have a bunch of future timers configured. Nodejs keeps the timers in a sorted linked list and the event loop just checks the time for the next timer to fire - the one at the front of the sorted list (the rest of the timers are not looked at until they get to the front of the sorted list). This means the only time it costs anything to have lots of future timers is when inserting a new timer into the sorted list and there is no regular cost in the event loop to having lots of pending timers present.
In this Node app I'm working on, it's possible for users to book appointments.
When an appointment is booked, the users will later get a reminder by mail X hours before the actual appointment.
I'm thinking about using Node-schedule for this task.
For each appointment: Set up a future Date, send the reminder mail once and the delete this particular scheduled job
But... there might be ALOT of appointments booked when the app grows, and this means there will be ALOT of Node-schedule processes simultaneously sleeping and waiting to fire...
On a regular day, lets pretend we have 180 appointments booked for the future per clients, and lets pretend the app right now has 50 clients. This gives us around 9000 scheduled tasks sleeping and waiting to fire.
Question: Is this perfectly OK? ... or will all these simultaneously scheduled task be to much/many?
Short answer: 9000 is not a lot, you're good to go. However, I would advise you to write a benchmark to see for yourself.
I checked node-schedule's source and sure enough, it delegates scheduling to setTimeout for date-based tasks. This means that your jobs are scheduled using node.js internal event loop.
This code is very efficient, as node.js is tailored to handle several thousands of requests simultaneously.
Regardless of the number of pending jobs, node.js will only care about the next task and sleep until its date (unless an async I/O interrupts it), so scheduling a task is essentially O(1).
I'd like to write an extension that displays a desktop notification every day at a specified time. Having a quick look through the Chrome APIs, it seems like the only way to do this would be to:
create a background page for my extension,
use setInterval() with a sufficiently low resolution to not tax the CPU (even 5 min is fine),
when interval fires, check if the current time is after the desired time,
ensure that the user has not already been displayed the notification today.
(The details of the last step are irrelevant to my question, just put in to show I realize I need to prevent "flapping" of the notice).
This seems rather indirect and potentially expensive though; is there any way around this? Is the background page needed?
I suppose I could just call setTimeout() and only fire the event once (by calculating how long between now & desired time), then call it again after the notification is shown. For some reason that sounds more "brittle", though I'm not sure why...
I think you will want the background page to do this smoothly. You can't use a content script because you need to keep the "state"/timer.
So when background page first loads (browser start) you work out the current time and the offset to the next notification time and setInterval to that exact interval. That way you won't need to poll every five minutes and/or work out if you've shown the message. You simply show it at the exact time required. This has to be far more efficient, effective and cleaner than polling. At notification you just reset the interval again.
Some sample functions here:
setTimeout but for a given time
From reading the above post and from a quick search on the net it appears that you should have no problem calling setInterval for an interval such as once a day. Calvin suggests 25 days!
That is how I would approach it.
EDIT: Since posting one thing that has sprung to mind is what happens if a PC gets hibernated for n hours? I need to test this myself for a similar project so I will update once I've had a chance to test this out.
I have a application in which i am sending a SMS to the Server which will return the result as an SMS. So i have put a Message Intercepter with the Event Handler. The Problem is that Once i send the request i have to wait for 30 seconds before i go ahead with the operation. How do i make my application wait till that. if i use the Thread.sleep it is making the whole application sleep and i am not getting any response out there.
Any idea how to tackle this
Thanks in Advance
Regards
Biju
What I assume you are trying to do is prevent the user from advancing until they receive a valid response from SMS, as some kind of authentication with a timeout of 30 seconds if the response was not received.
To do this, you could display a modal dialog that just displays the "Waiting for SMS Response.." message and close the dialog once 30 seconds have elapsed (using a Timer) or a response is received from SMS.
The event should fire asynchronously, so your program continues. You can have the event handler set a flag to continue on whatever path your program is taking.
also, as a side note, if you ever find yourself thinking "gee, Thread.Sleep(1000) would work great here" take a step back and examine the situation. Most of the time, you can do it asynchronously with events.
It sounds like you could use a timer of some kind. If you need to execute your code within the UI thread, you could use a System.Windows.Forms.Timer; if you're happy with it executing in a thread pool thread you could use System.Threading.Timer or System.Timers.Timer.
I don't know offhand which of these are available in the Compact Framework, but I'd expect at least one of them to be.
If they're really not available, one option which is kinda hacky but would work is to create a new thread which just sleeps for 30 seconds and then either executes the code you need or marshals to the UI thread (using Control.Invoke/BeginInvoke) to execute there if necessary. It's about as crude a timer as you can get, but it should work.