diff --git a/examples/GracefulShutdown.js b/examples/GracefulShutdown.js new file mode 100644 index 00000000..10c3e4d0 --- /dev/null +++ b/examples/GracefulShutdown.js @@ -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); + } +}); diff --git a/src/AppWrapper.h b/src/AppWrapper.h index 76860c82..3c24b5d7 100644 --- a/src/AppWrapper.h +++ b/src/AppWrapper.h @@ -160,7 +160,7 @@ void uWS_App_listen(const FunctionCallbackInfo &args) { int port = args[0]->Uint32Value(args.GetIsolate()->GetCurrentContext()).ToChecked(); app->listen(port, [&args](auto *token) { - Local argv[] = {Boolean::New(isolate, token)}; + Local argv[] = {External::New(isolate, token)}; Local::Cast(args[1])->Call(isolate->GetCurrentContext()->Global(), 1, argv); }); diff --git a/src/addon.cpp b/src/addon.cpp index 96f28978..b273f087 100644 --- a/src/addon.cpp +++ b/src/addon.cpp @@ -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 &args) { + us_listen_socket_close((struct us_listen_socket *) External::Cast(*args[0])->Value()); +} + void Main(Local exports) { /* I guess we store this statically */ isolate = exports->GetIsolate(); - /* Register our own nextTick handler */ + /* Register our own nextTick handlers */ uWS::Loop::defaultLoop()->setPostHandler([](uWS::Loop *) { emptyNextTickQueue(isolate); }); - /* Also empty in pre, it doesn't matter */ + /* We also do need it on pre */ uWS::Loop::defaultLoop()->setPreHandler([](uWS::Loop *) { emptyNextTickQueue(isolate); }); @@ -75,7 +80,8 @@ void Main(Local exports) { exports->Set(String::NewFromUtf8(isolate, "SSLApp"), FunctionTemplate::New(isolate, uWS_App)->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 */ WebSocketWrapper::initWsTemplate<0>();