Improved ghost-server with async/await
- Using consistent patterns for shutdown and stop - Make it clear what each method does - Use async/await to make the code more readable and simple - This lays groundwork for having more cleanup tasks in stop than just server.stop()
This commit is contained in:
parent
1f69b22b30
commit
624206b6d7
@ -14,7 +14,6 @@ const logging = require('../shared/logging');
|
||||
const moment = require('moment');
|
||||
const bootstrapSocket = require('@tryghost/bootstrap-socket');
|
||||
const stoppable = require('stoppable');
|
||||
const {reject} = require('bluebird');
|
||||
|
||||
/**
|
||||
* ## GhostServer
|
||||
@ -103,7 +102,7 @@ class GhostServer {
|
||||
|
||||
self.httpServer.on('listening', function () {
|
||||
debug('...Started');
|
||||
self.logStartMessages();
|
||||
self._logStartMessages();
|
||||
|
||||
return GhostServer.announceServerReadiness()
|
||||
.finally(() => {
|
||||
@ -113,21 +112,10 @@ class GhostServer {
|
||||
|
||||
stoppable(self.httpServer, config.get('server:shutdownTimeout'));
|
||||
|
||||
async function shutdown() {
|
||||
try {
|
||||
logging.warn(i18n.t('notices.httpServer.ghostIsShuttingDown'));
|
||||
await self.stop();
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
logging.error(error);
|
||||
process.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that Ghost exits correctly on Ctrl+C and SIGTERM
|
||||
process
|
||||
.removeAllListeners('SIGINT').on('SIGINT', shutdown)
|
||||
.removeAllListeners('SIGTERM').on('SIGTERM', shutdown);
|
||||
.removeAllListeners('SIGINT').on('SIGINT', self.shutdown.bind(self))
|
||||
.removeAllListeners('SIGTERM').on('SIGTERM', self.shutdown.bind(self));
|
||||
|
||||
if (config.get('server:testmode')) {
|
||||
// Debug code
|
||||
@ -138,48 +126,68 @@ class GhostServer {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* ### Shutdown
|
||||
* Stops the server, handles cleanup and exits the process = a full shutdown
|
||||
* Called on SIGINT or SIGTERM
|
||||
*/
|
||||
async shutdown() {
|
||||
try {
|
||||
logging.warn(i18n.t('notices.httpServer.ghostIsShuttingDown'));
|
||||
await this.stop();
|
||||
process.exit(0);
|
||||
} catch (error) {
|
||||
logging.error(error);
|
||||
process.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ### Stop
|
||||
* Returns a promise that will be fulfilled when the server stops. If the server has not been started,
|
||||
* the promise will be fulfilled immediately
|
||||
* Stops the server & handles cleanup, but does not exit the process
|
||||
* Used in tests for quick start/stop actions
|
||||
* Called by shutdown to handle server stop and cleanup before exiting
|
||||
* @returns {Promise} Resolves once Ghost has stopped
|
||||
*/
|
||||
stop() {
|
||||
const self = this;
|
||||
async stop() {
|
||||
if (this.httpServer === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
return new Promise(function (resolve) {
|
||||
if (self.httpServer === null) {
|
||||
resolve(self);
|
||||
} else {
|
||||
// The stop function comes from stoppable
|
||||
self.httpServer.stop(function (err) {
|
||||
if (err) {
|
||||
reject(self);
|
||||
}
|
||||
|
||||
events.emit('server.stop');
|
||||
self.httpServer = null;
|
||||
self.logStopMessages();
|
||||
resolve(self);
|
||||
});
|
||||
}
|
||||
});
|
||||
await this._stopServer();
|
||||
events.emit('server.stop');
|
||||
this.httpServer = null;
|
||||
this._logStopMessages();
|
||||
}
|
||||
|
||||
/**
|
||||
* ### Hammertime
|
||||
* To be called after `stop`
|
||||
*/
|
||||
hammertime() {
|
||||
async hammertime() {
|
||||
logging.info(i18n.t('notices.httpServer.cantTouchThis'));
|
||||
}
|
||||
|
||||
return Promise.resolve(this);
|
||||
/**
|
||||
* ### Stop Server
|
||||
* Does the work of stopping the server using stoppable
|
||||
* This handles closing connections:
|
||||
* - New connections are rejected
|
||||
* - Idle connections are closed immediately
|
||||
* - Active connections are allowed to complete in-flight requests before being closed
|
||||
*
|
||||
* If server.shutdownTimeout is reached, requests are terminated in-flight
|
||||
*/
|
||||
async _stopServer() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.httpServer.stop((err, status) => (err ? reject(err) : resolve(status)));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* ### Log Start Messages
|
||||
*/
|
||||
logStartMessages() {
|
||||
_logStartMessages() {
|
||||
logging.info(i18n.t('notices.httpServer.ghostIsRunningIn', {env: config.get('env')}));
|
||||
|
||||
if (config.get('env') === 'production') {
|
||||
@ -197,8 +205,9 @@ class GhostServer {
|
||||
|
||||
/**
|
||||
* ### Log Stop Messages
|
||||
* Private / internal API
|
||||
*/
|
||||
logStopMessages() {
|
||||
_logStopMessages() {
|
||||
logging.warn(i18n.t('notices.httpServer.ghostHasShutdown'));
|
||||
|
||||
// Extra clear message for production mode
|
||||
|
Loading…
Reference in New Issue
Block a user