How does the event: 'close' work in Node.js? - node.js

I'm experimenting with the close event in Node.js. I'm very new to Node.js so I'm not sure if this is a decent question or a sad one.
Documentation for close event:
http://nodejs.org/api/http.html#http_event_close_2
I want to output to the console a message if the browser is closed before the end event is reached.
While the server ran and before it got to 15 seconds, I tried closing the browser and killing the process through Chrome Tools. No message is output to the console and if I open up other connections by visiting localhost:8080 with other windows, I quickly get a 'hello' indicating my node server thinks there are at least two connections.
I'm either not understanding how to kill processes in Chrome or how the event close works.
Or if End and Close are the same - node.js https no response 'end' event, 'close' instead? - why isn't my "They got impatient!" message still ouput in the console?
How can you output to a console if the process was ended before the event end was reached?
var http = require('http'),
userRequests = 0;
http.createServer(function(request,response){
userRequests++;
response.writeHead(200, {'Content-Type' : 'text/plain'});
if ( userRequests == 1 ){
response.write('1st \n');
setTimeout ( function() {
response.write('2nd Thanks for waiting. \n');
response.on('close', function() {
console.log("They got impatient!");
});
response.end();
}, 15000);
response.write('3rd \n');
}
else {
// Quick response for all connections after first user
response.write('Hello');
response.end();
}
}).listen(8080, function() {
console.log('Server start');
});
Thank you.

First - move the event handler for the close message outside the timeout function - you're not hooking up the close handler until after your timeout expires, and probably missing the event.
Second, you never decrement userRequests anywhere; shouldn't there be a userRequests--; line somewhere? This would be throwing off your logic, since it'll always look like there's more than one request.

Related

Node.JS event loop socket delayed or thread blocked

I have a problem with node.js when sending a lot of concurrent request. The problem is that sometimes it seems it puts some request at the end of the event pool and give me the response after some serious time (60 seconds+, normal is under 10 seconds).
The story goes like this, i have 3 scripts, a CONSOLE, a SERVER and 10 CLIENTS.
console.js
// sending message
client.connect(port, host, function(connect_socket)
{
client.sendMessage(code:301,... some json-socket message ...);
client.on('message', function(message)
{
if(message.code == 304)
{
console.log(... print data ...)
}
});
}
server.js
server = net.createServer(function(socket)
{
socket = new JsonSocket(socket);
socket.on('message', function(message)
{
if(message.code == 301)
{
var client_random = get_random_client();
client_random.sendMessage(code:302,... some json-socket message ...);
}
if(message.code == 303)
{
var client_return = get_client_by_id(message.return_client_id);
client_return.sendMessage(code:304,... some json-socket message ...);
}
});
});
});
client.js
client.connect(port, host, function(connect_socket)
{
client.on('message', function(message)
{
if(message.code == 302)
{
execute_command(message.data, function(result_command)
{
client.sendMessage(code:303,... some json-socket message (good or bad check) ...)
});
}
});
}
Arhitecture concept, console sends message to server, server to a random client, client executes an external program and sends output back to server, server sends response back to the console and console prints it.
console.js => server.js => client.js => server.js => console.js
I open the server, clients are connecting no problem. I open the console and type the command, i get every time the response under 10 seconds.
Now, i made another PHP script that would simulate 600 requests per second. I do the same thing, open console, send command, and once every 10 runs (1 of 10), the console waits, waits and waits, and after 60 seconds it gives me the result (10 was normal).
I made some debug and it seems that server.js do not trigger message event when reciving from client.js and somehow puts it at the very end of the event pool, but never forget it, runs eventually.
I have double check :
console.js every time sends message to server.js (always instant)
server.js every time sends message to client.js (always instant)
client.js every time sends message to server.js (always instant)
[server.js do not fire the event message event instant, and put it
on the very end of the event pool ]
server.js every time sends message to client.js (always instant)
Also i have checked for the possible I/O main thread block, everything is fine. All operations are async, no sync functions.
It is that kind of bug that sometime it is manifesting, sometimes not. Like after a console.js waiting, you can open another terminal and console.js and send messages and see how it responds right away. As i already told, it is like a probability of 1 from 10.
How can i solve this? I had made a lot of debugging.

NodeJS Child Process can't send net.socket fd:3

When writing a nodejs multi-threading package there is the problem when the main thread can send content though fd:3 and threads can receive the message, but then threads cannot send anything back though fd:3
Is there something I am doing wrong? (line threader.js:45-59 is where the problem shows it's self)
Package (Only on github for now while I get the package working)
Start up code:
var Thread = require("threader");
var task = Thread.task(function(){
//Do some calculation
}, function(){
//When the calculation response has been sent
});
task('a', 2);
I just figured the problem:
thread.js is like a socket Server and threader.js is like a client.
Server has to respond with in the context of the connection.
Since you are using setTimeout which itself is a separate thread that doesn't have access to the connection context, threader is not able to listen to data.
thread.js - old code
pipe.on('data', function(chunk){
console.log('RECEIVED CONENT THOUGH fd:3 in thread');
console.log(chunk.toString());
});
setTimeout(function () {
pipe.write('I piped a thing');
}, 2000);
thread.js - new code
pipe.on('data', function(chunk){
console.log('RECEIVED CONENT THOUGH fd:3 in thread');
console.log(chunk.toString());
});
pipe.write('I piped a thing');
OR
thread.js - new code - best way
pipe.on('data', function(chunk){
console.log('RECEIVED CONENT THOUGH fd:3 in thread');
console.log(chunk.toString());
//Real 2 second work but not on a separate thread using setTimeout
pipe.write('I piped a thing');
});
I just rewrote the entire package again starting for a different angle and now it works...
I think the problem was to do with the thread picking.
The fixes will be pushed to github soon.

Can’t gracefully shut down a node + Express app (node http server's close function does not complete)

I want the Express.js-based server of the app I am working on to properly close all connections before exiting the node process when a shutdown signal (SIGTERM or SIGINT) is sent.
I have slightly modified the express-graceful-shutdown middleware (which is really simple), so the relevant part of my code looks approximately as follows:
server.js
import gracefulShutdown from './tools/graceful-shutdown';
const server = app.listen(config.port, () => {
console.log(`Server is running`);
});
app.use(gracefulShutdown(server));
graceful-shutdown.js:
function gracefulShutdownMiddleware(server) {
let shuttingDown = false;
const forceTimeout = 10 * 1000; // giving the app 10 seconds to shutdown gracefully
process.on('SIGTERM', gracefulExit); // listen for TERM signal (e.g. kill)
process.on ('SIGINT', gracefulExit); // listen for INT signal (e.g. Ctrl-C)
function gracefulExit() {
if (shuttingDown) return;
shuttingDown = true;
console.log('Received kill signal (SIGTERM), shutting down');
setTimeout(function () {
console.log('Could not close connections in time, forcefully shutting down');
process.exit(1);
}, forceTimeout);
server.close(function () {
console.log('Closed out remaining connections.');
process.exit();
});
}
function middleware(req, res, next) {
if (!shuttingDown) return next()
res.set('Connection', 'close')
res.status(503).send('Server is in the process of restarting.')
}
return middleware
}
export default gracefulShutdownMiddleware;
The problem I am observing is this. If I shut down the node server immediately after it starts, it shuts down as expected (function gracefulExit in the middleware works correctly, server.close executes fine, and the callback to server.close prints out the console message). If, however, I open the browser and actually visit my app on the localhost, so that the server has some work to do, and then try to shut the server down, the server.close function does not seem to finish (so it never calls the callback with process.exit until finally the setTimeout calls its own callback and forcefully shuts down the app.
The server.close function is this function from node’s lib.
Could you help me figure out why node server’s close function may fail to complete?
.close() doesn't actually close any active connections, it will only stop new connections from being made, and it'll wait for the active connections to get closed (by the client).
If clients are connected that keep a connection open (say using a keep-alive connection), the callback may never get called.
There's a package called http-shutdown that will help with gracefully shutting down an HTTP server.

How do I stop a Node.js HTTP server programmatically such that the process exits?

I'm writing some tests and would like to be able to start/stop my HTTP server programmatically. Once I stop the HTTP server, I would like the process that started it to exit.
My server is like:
// file: `lib/my_server.js`
var LISTEN_PORT = 3000
function MyServer() {
http.Server.call(this, this.handle)
}
util.inherits(MyServer, http.Server)
MyServer.prototype.handle = function(req, res) {
// code
}
MyServer.prototype.start = function() {
this.listen(LISTEN_PORT, function() {
console.log('Listening for HTTP requests on port %d.', LISTEN_PORT)
})
}
MyServer.prototype.stop = function() {
this.close(function() {
console.log('Stopped listening.')
})
}
The test code is like:
// file: `test.js`
var MyServer = require('./lib/my_server')
var my_server = new MyServer();
my_server.on('listening', function() {
my_server.stop()
})
my_server.start()
Now, when I run node test.js, I get the stdout output that I expect,
$ node test.js
Listening for HTTP requests on port 3000.
Stopped listening.
but I have no idea how to get the process spawned by node test.js to exit and return back to the shell.
Now, I understand (abstractly) that Node keeps running as long as there are bound event handlers for events that it's listening for. In order for node test.js to exit to the shell upon my_server.stop(), do I need to unbind some event? If so, which event and from what object? I have tried modifying MyServer.prototype.stop() by removing all event listeners from it but have had no luck.
I've been looking for an answer to this question for months and I've never yet seen a good answer that doesn't use process.exit. It's quite strange to me that it is such a straightforward request but no one seems to have a good answer for it or seems to understand the use case for stopping a server without exiting the process.
I believe I might have stumbled across a solution. My disclaimer is that I discovered this by chance; it doesn't reflect a deep understanding of what's actually going on. So this solution may be incomplete or maybe not the only way of doing it, but at least it works reliably for me. In order to stop the server, you need to do two things:
Call .end() on the client side of every opened connection
Call .close() on the server
Here's an example, as part of a "tape" test suite:
test('mytest', function (t) {
t.plan(1);
var server = net.createServer(function(c) {
console.log("Got connection");
// Do some server stuff
}).listen(function() {
// Once the server is listening, connect a client to it
var port = server.address().port;
var sock = net.connect(port);
// Do some client stuff for a while, then finish the test
setTimeout(function() {
t.pass();
sock.end();
server.close();
}, 2000);
});
});
After the two seconds, the process will exit and the test will end successfully. I've also tested this with multiple client sockets open; as long as you end all client-side connections and then call .close() on the server, you are good.
http.Server#close
https://nodejs.org/api/http.html#http_server_close_callback
module.exports = {
server: http.createServer(app) // Express App maybe ?
.on('error', (e) => {
console.log('Oops! Something happened', e));
this.stopServer(); // Optionally stop the server gracefully
process.exit(1); // Or violently
}),
// Start the server
startServer: function() {
Configs.reload();
this.server
.listen(Configs.PORT)
.once('listening', () => console.log('Server is listening on', Configs.PORT));
},
// Stop the server
stopServer: function() {
this.server
.close() // Won't accept new connection
.once('close', () => console.log('Server stopped'));
}
}
Notes:
"close" callback only triggers when all leftover connections have finished processing
Trigger process.exit in "close" callback if you want to stop the process too
To cause the node.js process to exit, use process.exit(status) as described in http://nodejs.org/api/process.html#process_process_exit_code
Update
I must have misunderstood.
You wrote: "...but I have no idea how to get the process spawned by node test.js to exit and return back to the shell."
process.exit() does this.
Unless you're using the child_processes module, node.js runs in a single process. It does not "spawn" any further processes.
The fact that node.js continues to run even though there appears to be nothing for it to do is a feature of its "event loop" which continually loops, waiting for events to occur.
To halt the event loop, use process.exit().
UPDATE
After a few small modifications, such as the proper use of module.exports, addition of semicolons, etc., running your example on a Linux server (Fedora 11 - Leonidas) runs as expected and dutifully returns to the command shell.
lib/my_server.js
// file: `lib/my_server.js`
var util=require('util'),
http=require('http');
var LISTEN_PORT=3000;
function MyServer(){
http.Server.call(this, this.handle);
}
util.inherits(MyServer, http.Server);
MyServer.prototype.handle=function(req, res){
// code
};
MyServer.prototype.start=function(){
this.listen(LISTEN_PORT, function(){
console.log('Listening for HTTP requests on port %d.', LISTEN_PORT)
});
};
MyServer.prototype.stop=function(){
this.close(function(){
console.log('Stopped listening.');
});
};
module.exports=MyServer;
test.js
// file: `test.js`
var MyServer = require('./lib/my_server');
var my_server = new MyServer();
my_server.on('listening', function() {
my_server.stop();
});
my_server.start();
Output
> node test.js
Listening for HTTP requests on port 3000.
Stopped listening.
>
Final thoughts:
I've found that the conscientious use of statement-ending semicolons has saved me from a wide variety of pernicious, difficult to locate bugs.
While most (if not all) JavaScript interpreters provide something called "automatic semicolon insertion" (or ASI) based upon a well-defined set of rules (See http://dailyjs.com/2012/04/19/semicolons/ for an excellent description), there are several instances where this feature can inadvertently work against the intent of the programmer.
Unless you are very well versed in the minutia of JavaScript syntax, I would strongly recommend the use of explicit semicolons rather than relying upon ASI's implicit ones.

NodeJS socket.io-client doesn't fire 'disconnect' or 'close' events when the server is killed

I've written up a minimal example of this. The code is posted here: https://gist.github.com/1524725
I start my server, start my client, verify that the connection between the two is successful, and finally kill the server with CTRL+C. When the server dies, the client immediately runs to completion and closes without printing the message in either on_client_close or on_client_disconnect. There is no perceptible delay.
From the reading I've done, because the client process is terminating normally there isn't any chance that the STDOUT buffer isn't being flushed.
It may also be worth noting that when I kill the client instead of the server, the server responds as expected, firing the on_ws_disconnect function and removing the client connection from its list of active clients.
32-bit Ubuntu 11.10
Socket.io v0.8.7
Socket.io-client v0.8.7
NodeJS v0.6.0
Thanks!
--- EDIT ---
Please note that both the client and the server are Node.js processes rather than the conventional web browser client and node.js server.
NEW ANSWER
Definitely a bug in io-client. :(
I was able to fix this by modifying socket.io-client/libs/socket.js. Around line 433, I simply moved the this.publish('disconnect', reason); above if (wasConnected) {.
Socket.prototype.onDisconnect = function (reason) {
var wasConnected = this.connected;
this.publish('disconnect', reason);
this.connected = false;
this.connecting = false;
this.open = false;
if (wasConnected) {
this.transport.close();
this.transport.clearTimeouts();
After pressing ctrl+c, the disconnect message fires in roughly ten seconds.
OLD DISCUSSION
To notify client of shutdown events, you would add something like this to demo_server.js:
var logger = io.log;
process.on('uncaughtException', function (err) {
if( io && io.socket ) {
io.socket.broadcast.send({type: 'error', msg: err.toString(), stack: err.stack});
}
logger.error(err);
logger.error(err.stack);
//todo should we have some default resetting (restart server?)
app.close();
process.exit(-1);
});
process.on('SIGHUP', function () {
logger.error('Got SIGHUP signal.');
if( io && io.socket ) {
io.socket.broadcast.send({type: 'error', msg: 'server disconnected with SIGHUP'});
}
//todo what happens on a sighup??
//todo if you're using upstart, just call restart node demo_server.js
});
process.on('SIGTERM', function() {
logger.error('Shutting down.');
if( io && io.socket ) {
io.socket.broadcast.send({type: 'error', msg: 'server disconnected with SIGTERM'});
}
app.close();
process.exit(-1);
});
Of course, what you send in the broadcast.send(...) (or even which command you use there) depends on your preference and client structure.
For the client side, you can tell if the server connection is lost using on('disconnect', ...), which you have in your example:
client.on('disconnect', function(data) {
alert('disconnected from server; reconnecting...');
// and so on...
});

Resources