Add us_listen_socket_close and graceful shutdown example

This commit is contained in:
Alex Hultman 2019-01-18 09:07:21 +01:00
parent ab829af8ce
commit 0fb6ec9034
3 changed files with 49 additions and 4 deletions

View File

@ -0,0 +1,39 @@
/* Minimal example that shuts down gracefully */
const uWS = require('../dist/uws.js');
const port = 9001;
/* We store the listen socket here, so that we can shut it down later */
let listenSocket;
const app = uWS./*SSL*/App({
key_file_name: 'misc/key.pem',
cert_file_name: 'misc/cert.pem',
passphrase: '1234'
}).get('/shutdown', (res, req) => {
if (listenSocket) {
res.end('Okay, shutting down now!');
/* This function is provided directly by µSockets */
uWS.us_listen_socket_close(listenSocket);
listenSocket = null;
} else {
/* We just refuse if alrady shutting down */
res.close();
}
}).listen(port, (token) => {
/* Save the listen socket for later shut down */
listenSocket = token;
/* Did we even manage to listen? */
if (token) {
console.log('Listening to port ' + port);
/* Stop listening soon */
setTimeout(() => {
console.log('Shutting down now');
uWS.us_listen_socket_close(listenSocket);
listenSocket = null;
}, 1000);
} else {
console.log('Failed to listen to port ' + port);
}
});

View File

@ -160,7 +160,7 @@ void uWS_App_listen(const FunctionCallbackInfo<Value> &args) {
int port = args[0]->Uint32Value(args.GetIsolate()->GetCurrentContext()).ToChecked(); int port = args[0]->Uint32Value(args.GetIsolate()->GetCurrentContext()).ToChecked();
app->listen(port, [&args](auto *token) { app->listen(port, [&args](auto *token) {
Local<Value> argv[] = {Boolean::New(isolate, token)}; Local<Value> argv[] = {External::New(isolate, token)};
Local<Function>::Cast(args[1])->Call(isolate->GetCurrentContext()->Global(), 1, argv); Local<Function>::Cast(args[1])->Call(isolate->GetCurrentContext()->Global(), 1, argv);
}); });

View File

@ -53,16 +53,21 @@ void emptyNextTickQueue(Isolate *isolate) {
} }
} }
/* todo: Put this function and all inits of it in its own header */
void uWS_us_listen_socket_close(const FunctionCallbackInfo<Value> &args) {
us_listen_socket_close((struct us_listen_socket *) External::Cast(*args[0])->Value());
}
void Main(Local<Object> exports) { void Main(Local<Object> exports) {
/* I guess we store this statically */ /* I guess we store this statically */
isolate = exports->GetIsolate(); isolate = exports->GetIsolate();
/* Register our own nextTick handler */ /* Register our own nextTick handlers */
uWS::Loop::defaultLoop()->setPostHandler([](uWS::Loop *) { uWS::Loop::defaultLoop()->setPostHandler([](uWS::Loop *) {
emptyNextTickQueue(isolate); emptyNextTickQueue(isolate);
}); });
/* Also empty in pre, it doesn't matter */ /* We also do need it on pre */
uWS::Loop::defaultLoop()->setPreHandler([](uWS::Loop *) { uWS::Loop::defaultLoop()->setPreHandler([](uWS::Loop *) {
emptyNextTickQueue(isolate); emptyNextTickQueue(isolate);
}); });
@ -75,7 +80,8 @@ void Main(Local<Object> exports) {
exports->Set(String::NewFromUtf8(isolate, "SSLApp"), FunctionTemplate::New(isolate, uWS_App<uWS::SSLApp>)->GetFunction()); exports->Set(String::NewFromUtf8(isolate, "SSLApp"), FunctionTemplate::New(isolate, uWS_App<uWS::SSLApp>)->GetFunction());
exports->Set(String::NewFromUtf8(isolate, "nextTick"), FunctionTemplate::New(isolate, nextTick)->GetFunction()); exports->Set(String::NewFromUtf8(isolate, "nextTick"), FunctionTemplate::New(isolate, nextTick)->GetFunction());
// these inits should probably happen elsewhere (in their respective struct's constructor)? /* Expose some µSockets functions directly under uWS namespace */
exports->Set(String::NewFromUtf8(isolate, "us_listen_socket_close"), FunctionTemplate::New(isolate, uWS_us_listen_socket_close)->GetFunction());
/* The template for websockets */ /* The template for websockets */
WebSocketWrapper::initWsTemplate<0>(); WebSocketWrapper::initWsTemplate<0>();