I have a node app that connects to a server, so that my code can easily send data to it since I just leave the connection open constantly. But the problem is that the app never exits because the connection is still active, even after it's done being used.
The problem is there isn't one solid code path, so there isn't one place that I could end the connection. Is there a way to tell node to exit as soon as all the other code is finished, even though the connection is still open?
I'm going for something like fs.watchFile
process.exit(exitCode)
http://nodejs.org/api/process.html#process_process_exit_code
Aside: It really sounds like the code is due for a refactor with clear socket handling in mind. Refactor early, refactor often.
Related
I have a working WebRTC JavaScript application. Here is the problem: if during a web call there is a bad network connection, the call is stopped without WebRTC attempting to reconnect.
I would like to improve the code of my application by adding an automatic reconnection attempt system, however, in order to do so I need to understand some theory about WebRTC (and I think this can be very useful for many other developers).
Here are my questions:
Does WebRTC have a native functionality to attempt reconnection if the network is bad or should I listen for some "disconnection tigger" and call "a function" to start a new connection from zero?
If things cannot be done magically, what is/are the right "disconnection tigger/s" and "the function" from which the reconnection attempt process should restart? Is there something that can (or should) be taken from the previous connection?
I have read about an {iceRestart: true} parameter. Should this be used for the first call (then WebRTC will magically handle disconnection by attempting to reconnect) or should I use it ONLY when my code attempts to reconnect (on the 2nd, 3rd times...)?
What is the difference between connectionState "disconnected", "failed" and "closed" and does it have something to do with attempting to reconnect with bad network?
What is the best way to avoid attempting to reconnect in an infinite loop if there is no hope to reconnect (i.e: internet completely down)?
What is the difference between oniceconnectionstatechange and onconnectionstatechange? which is relevant in my case?
Thanks!
Luca
I was able to find the (JavaScript) solution through experimenting...
1) Does WebRTC have a native functionality to attempt reconnection if the network is bad or should I listen for some "disconnection tigger" and call "a function" to start a new connection from zero?
Yes, it does it by default in JavaScript, unless your code handles disconnection by proactively terminating the call through additional lines of instructions.
2) If things cannot be done magically, what is/are the right "disconnection tigger/s" and "the function" from which the reconnection attempt process should restart? Is there something that can (or should) be taken from the previous connection?
Things already happen under the hood (by magic). If the code terminates the call, it is probably because the disconnection trigger (ICE connection state = disconnected OR connection state = disconnected) triggers some additional code from the app you copy/pasted from somewhere.
3) I have read about an {iceRestart: true} parameter. Should this be used for the first call (then WebRTC will magically handle disconnection by attempting to reconnect) or should I use it ONLY when my code attempts to reconnect (on the 2nd, 3rd times...)?
Not useful in this scenario.
4) What is the difference between connectionState "disconnected", "failed" and "closed" and does it have something to do with attempting to reconnect with bad network?
You have to listen for connectionState = disconnected, the other ones don't matter for this purpose.
5) What is the best way to avoid attempting to reconnect in an infinite loop if there is no hope to reconnect (i.e: internet completely down)?
No problem, the reconnection WebRTC handles automatically will not cost anything in terms of signaling, therefore, you can try to reconnect as many times as you want, the user will eventually exit the call on his own if things are too slow.
6) What is the difference between oniceconnectionstatechange and onconnectionstatechange? which is relevant in my case?
No difference in this case, the only difference is that the ice state change is triggered right before the connection state change.
--
I hope this will be helpful to somebody!
So I'm trying to have my bot restart ENTIRELY on encountering an error. The reason why I don't just let it sift through connection errors is because, whenever I encounter an internet issue, code starts repeating multiple times since the original node process hasn't been terminated, which technically I could fix but other connections to external apis stop working too. So ignoring fixing singular issues, I just want to restart entirely.
What I'm doing currently is using node child_process, with this function:
spawn(process.argv.shift(), process.argv, {
cwd: process.cwd(),
detached : true,
stdio: "inherit"
});
process.exit();
I do know stdio inherit does nothing, since its exiting the parent process, but it doesn't really change anything to put it to ignore so i've just left it. Basically this works in theory, if I use a command to execute this, i can do it over and over and over and it will work fine, singular discord client, no repeats, it's up, i just can't monitor it since my original terminal is disconnected, and I can use a command to exit the current process so it's not stuck since I don't have a terminal to ctrl-c. But once put in practice, executing the function in bot.on("error") by disconnecting my internet seems to work, it ends the first process, but upon regaining internet there is no client connected.
My guess here: bot.on("error") will not be re-executed in the next process due to no discord client being made.
So I don't know if I'm making this too complicated or if I need to add a lot more. If this is the best way to do it then all I would need to solve is to wait until I have internet back and then make a new process or something like that. I'm not educated in fiddling with node so if any answers could be beginner friendly (mainly for node) i'd really appreciate it.
bot.on("error", (err) => {
process.exit(0)
});
Should work, it'll restart the bot when there's an error.
Unsure what you mean by
My guess here: bot.on("error") will not be re-executed in the next process due to no discord client being made.
As long as you bot it in the same code as your startup, it'll restart the bot.
If you use a batch-file to run your bot simply add :a before the node . and goto a at the end.
On Node.js api there lots of ifs and one can easily send request with some undefined var and crash the whole server until it re-starts again - something that could take up to 20 seconds.
I know that it should be checked if a variable is defined before working with it. But its very easy to forget something and keep working with an undefined var.
Is there a global definition to the server to avoid such of a drop down?
The easiest solution I could think of is implementing a cluster, in which only one process will go down, not the whole server. You could also make the process to go up again automatically. See more here
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
} else {
// Workers can share any TCP connection
// In this case it is an HTTP server
http.createServer((req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}
In any application there are a lot of "ifs" and assumptions. With JavaScript, being weakly typed and dynamic, you can really shoot yourself in the foot.
But the same rules apply here as any other language. Practice defensive programming. That is, cover all the bases in each function and statement block.
You can also try out programming Nodejs with Typescript. It ads some static type checking and other nice features that help you miss your foot when you shoot. You can also use (I think) Flow to statically type check things. But these won't make you a better programmer.
One other suggestion is to design your system as a SOA. So that one portion going down doesn't necessarily affect others. "Microservices" being a subset of that.
First, defensive programming and extensive testing are your friends. Obviously, preventing an issue before it happens is much better than trying to react to it after it happens.
Second, there is no foolproof mechanism for catching all exceptions at some high level and then putting your server back into a known, safe state. You just can't really do that in any complex server because you don't know what you were in the middle of when the exception happened. People will often try to do this, but it's like proceeding with a wounded server that may have some messed up internals. It's not safe or advisable. If a problem was not intercepted (e.g. exception caught or error detected) at the level where it occurred by code that knows how to properly handle that situation, then the only completely safe path forward is to restart your server.
So, if after implementing as much defensive programming as you possibly can and testing the heck out of it, you still want to prevent end-user downtime from a server crash/restart, then the best way to do that is to assume that a given server process will occasionally need to be restarted and plan for that.
The simplest way to prevent end-user downtime when a server process restarts is to use clustering and thus have multiple server processes with some sort of load balancer that both monitors server processes and routes incoming connections among the healthy server processes. When one server process is down, it is temporarily taken out of the rotation and other server processes can handle new, incoming connections. When the failed server process is successfully restarted, it can be added back to the rotation and be used again for new requests. Clustering in this way can be done within a single server (multiple processes on the same server) or across servers (multiple servers, each with server processes on them).
In some cases, this same process can even be used to roll out a new version of server code without any system downtime (doing this requires additional planning).
I have socket.io running with Express. When I CTRL-C on the Terminal to stop the server running, the browser continues to report the following:
I found various similar questions, none of which have helped me resolve my question.
Could anyone show me how to tell socket.io to cancel reconnection attempts when the server stops running.
Many thanks in advance
I've found a solution.
I still wonder why some events in socket.io just don't seem to get fired but perhaps that's another question. The code that helped me resolve my question is:
var socket = io.connect('http://localhost:3000', {'reconnection': false});
Thank you for your contributions
The short answer:
Stop pressing CTRL-C, kidding.
The long answer:
There are a couple of things you could do:
1) You could change the reconnection options on the client, perhaps set reconnection to false. But maybe this is not desirable for the real world, so instead you could do:
2) Disconnect the client socket from the server right before the server exits. The exit strategy for this will depend on what server you use.
3) If options one and two are not viable, then there isn't much you could do since you are shutting down the server and leaving your client hanging — stuck in time thinking that the server will someday return. Not that it cares, though. You're console is the one with the big mouth...
I hope that helps!
My solution.
let socket = io.connect(null, {port:5000, rememberTransport: false});
I think this question is due to a lack of understanding on node, but i'm working on created a motion sensor with the raspberry pi and node.
I don't understand how to keep my node server running. I can get it to work as intended using setInterval but I don't think this is how I should be doing it.
Basically I want to be able to start the program with node index.js and have it continue watching the GPIO pins that the sensor is connected to see if something happens. If something happens then it does something, but keeps watching the sensor in case more happens.
What I have done to keep it running is similar to this:
var foo = require('require necessary things up here');
setInterval(function(){
//code for detecting sensor stuff here
}, 1000)
This works, but I know I don't think it's the right way to do it.
If I do something like the below it just executes the functions, logs to the console, but doesn't watch for changes and just exits out.
var foo = require('require necessary things up here')
function checkForSensorStuff(){
//code for detecting sensor stuff here
console.log('checking stuff')
}
How can I keep the server running so that it just continually watches for changes in a function without using setInterval?
A node process exits when it has nothing else left to do. You start a node process by running a startup script line by line. When that script finishes executing, if there's nothing else to do (no timers, no open sockets listening for incoming connections, etc...), then it shuts down because there's nothing left that could cause an event and cause some action on the server.
So, if you want your server to continue running, you have to give it some way for future events to occur. As you've discovered a recurring timer is one way to do that. There should be no reason to use a timer purely for keeping your server running. Instead you need to configure something in your server that will trigger events in the future. If you don't have anything that will cause future events, then you may need to use setInterval() to regularly poll some status to decide if there's something waiting to do.
If you're trying to monitor GPIO status on your Raspberry Pi in node.js, you can use the pigpio library and it will offer an event driven way of watching for GPIO changes. This should automatically keep your server running.
Another option for getting events upon GPIO changes is the onoff library.
I have a Raspberry Pi being used as a temperature controller that reads two GPIO temperature probes. I'm just using a setInterval() timer to poll the temperature readings every 10 seconds and that works just fine too.
I don't understand how to keep my node server running
You need to open an handle to a resource like a socket or a file. If there is no active handles opened, node exits. In your example setInterval is timer which prevents node to exit.
see also process._getActiveHandle
https://github.com/myndzi/wtfnode