Add maintenance mode and update to gracefully exit process on signal

This commit is contained in:
Cheng-Han, Wu 2016-06-01 14:18:54 +08:00
parent 27e17d7772
commit 16d5e3ea80
4 changed files with 43 additions and 3 deletions

26
app.js
View file

@ -502,3 +502,29 @@ process.on('uncaughtException', function (err) {
logger.error('Process will exit now.'); logger.error('Process will exit now.');
process.exit(1); process.exit(1);
}); });
// gracefully exit
process.on('SIGINT', function () {
config.maintenance = true;
// disconnect all socket.io clients
Object.keys(io.sockets.sockets).forEach(function (key) {
var socket = io.sockets.sockets[key];
// notify client server going into maintenance status
socket.emit('maintenance', config.version);
socket.disconnect(true);
});
var checkCleanTimer = setInterval(function () {
var usersCount = Object.keys(realtime.users).length;
var notesCount = Object.keys(realtime.notes).length;
// check if all users and notes array are empty
if (usersCount == 0 && notesCount == 0) {
// close db connection
models.sequelize.close();
clearInterval(checkCleanTimer);
// wait for a while before exit
setTimeout(function () {
process.exit(0);
}, 100);
}
}, 100);
});

View file

@ -78,10 +78,12 @@ function getserverurl() {
} }
var version = '0.4.0'; var version = '0.4.0';
var maintenance = config.maintenance || false;
var cwd = path.join(__dirname, '..'); var cwd = path.join(__dirname, '..');
module.exports = { module.exports = {
version: version, version: version,
maintenance: maintenance,
debug: debug, debug: debug,
urlpath: urlpath, urlpath: urlpath,
port: port, port: port,

View file

@ -25,7 +25,9 @@ var realtime = {
onAuthorizeFail: onAuthorizeFail, onAuthorizeFail: onAuthorizeFail,
secure: secure, secure: secure,
connection: connection, connection: connection,
getStatus: getStatus getStatus: getStatus,
users: users,
notes: notes
}; };
function onAuthorizeSuccess(data, accept) { function onAuthorizeSuccess(data, accept) {
@ -70,8 +72,9 @@ function emitCheck(note) {
} }
//actions //actions
var users = {}; var users, notes;
var notes = {}; realtime.users = users = {};
realtime.notes = notes = {};
//update when the note is dirty //update when the note is dirty
var updater = setInterval(function () { var updater = setInterval(function () {
async.each(Object.keys(notes), function (key, callback) { async.each(Object.keys(notes), function (key, callback) {
@ -536,6 +539,7 @@ function ifMayEdit(socket, callback) {
} }
function connection(socket) { function connection(socket) {
if (config.maintenance) return;
parseNoteIdFromSocket(socket, function (err, noteId) { parseNoteIdFromSocket(socket, function (err, noteId) {
if (err) { if (err) {
return failConnection(500, err, socket); return failConnection(500, err, socket);

View file

@ -1825,6 +1825,11 @@ socket.on('error', function (data) {
if (data.message && data.message.indexOf('AUTH failed') === 0) if (data.message && data.message.indexOf('AUTH failed') === 0)
location.href = "./403"; location.href = "./403";
}); });
var retryOnDisconnect = false;
socket.on('maintenance', function (data) {
if (data == version)
retryOnDisconnect = true;
});
socket.on('disconnect', function (data) { socket.on('disconnect', function (data) {
showStatus(statusType.offline); showStatus(statusType.offline);
if (loaded) { if (loaded) {
@ -1833,12 +1838,15 @@ socket.on('disconnect', function (data) {
} }
if (!editor.getOption('readOnly')) if (!editor.getOption('readOnly'))
editor.setOption('readOnly', true); editor.setOption('readOnly', true);
if (retryOnDisconnect)
socket.connect();
}); });
socket.on('reconnect', function (data) { socket.on('reconnect', function (data) {
//sync back any change in offline //sync back any change in offline
emitUserStatus(true); emitUserStatus(true);
cursorActivity(); cursorActivity();
socket.emit('online users'); socket.emit('online users');
retryOnDisconnect = false;
}); });
socket.on('connect', function (data) { socket.on('connect', function (data) {
personalInfo['id'] = socket.id; personalInfo['id'] = socket.id;