From b17bd15c467fb62a21cbee8f881de0f93d0df90c Mon Sep 17 00:00:00 2001 From: Bryan Ashby Date: Mon, 20 Jun 2016 20:39:20 -0600 Subject: [PATCH] * @watchFile support for event scheduler * Better/cleaner overall BBS shutdown WIP --- core/bbs.js | 68 ++++++++++++++++++++++++++--------------- core/event_scheduler.js | 30 ++++++++++++------ 2 files changed, 64 insertions(+), 34 deletions(-) diff --git a/core/bbs.js b/core/bbs.js index 0d6453d1..1020ee3e 100644 --- a/core/bbs.js +++ b/core/bbs.js @@ -5,22 +5,22 @@ //SegfaultHandler.registerHandler('enigma-bbs-segfault.log'); // ENiGMA½ -let conf = require('./config.js'); -let logger = require('./logger.js'); -let miscUtil = require('./misc_util.js'); -let database = require('./database.js'); -let clientConns = require('./client_connections.js'); +const conf = require('./config.js'); +const logger = require('./logger.js'); +const database = require('./database.js'); +const clientConns = require('./client_connections.js'); -let paths = require('path'); -let async = require('async'); -let util = require('util'); -let _ = require('lodash'); -let assert = require('assert'); -let mkdirs = require('fs-extra').mkdirs; +const async = require('async'); +const util = require('util'); +const _ = require('lodash'); +const mkdirs = require('fs-extra').mkdirs; // our main entry point exports.bbsMain = bbsMain; +// object with various services we want to de-init/shutdown cleanly if possible +const initServices = {}; + function bbsMain() { async.waterfall( [ @@ -84,6 +84,34 @@ function bbsMain() { ); } +function shutdownSystem() { + logger.log.info('Process interrupted, shutting down...'); + + async.series( + [ + function closeConnections(callback) { + const activeConnections = clientConns.getActiveConnections(); + let i = activeConnections.length; + while(i--) { + activeConnections[i].term.write('\n\nServer is shutting down NOW! Disconnecting...\n\n'); + clientConns.removeClient(activeConnections[i]); + } + callback(null); + }, + function stopEventScheduler(callback) { + if(initServices.eventScheduler) { + return initServices.eventScheduler.shutdown(callback); + } else { + return callback(null); + } + } + ], + () => { + process.exit(); + } + ); +} + function initialize(cb) { async.series( [ @@ -102,18 +130,7 @@ function initialize(cb) { function basicInit(callback) { logger.init(); - process.on('SIGINT', function onSigInt() { - logger.log.info('Process interrupted, shutting down...'); - - var activeConnections = clientConns.getActiveConnections(); - var i = activeConnections.length; - while(i--) { - activeConnections[i].term.write('\n\nServer is shutting down NOW! Disconnecting...\n\n'); - clientConns.removeClient(activeConnections[i]); - } - - process.exit(); - }); + process.on('SIGINT', shutdownSystem); // Init some extensions require('string-format').extend(String.prototype, require('./string_util.js').stringFormatExtensions); @@ -172,7 +189,10 @@ function initialize(cb) { }, function readyEventScheduler(callback) { const EventSchedulerModule = require('./event_scheduler.js').EventSchedulerModule; - EventSchedulerModule.loadAndStart(callback); + EventSchedulerModule.loadAndStart( (err, modInst) => { + initServices.eventScheduler = modInst; + return callback(err); + }); } ], function onComplete(err) { diff --git a/core/event_scheduler.js b/core/event_scheduler.js index fa8ec5f7..b4243a7a 100644 --- a/core/event_scheduler.js +++ b/core/event_scheduler.js @@ -10,6 +10,7 @@ const _ = require('lodash'); const later = require('later'); const path = require('path'); const pty = require('ptyw.js'); +const gaze = require('gaze'); exports.getModule = EventSchedulerModule; exports.EventSchedulerModule = EventSchedulerModule; // allow for loadAndStart @@ -102,8 +103,8 @@ class ScheduledEvent { } } - executeAction(cb) { - Log.info( { eventName : this.name, action : this.action }, 'Executing scheduled event action...'); + executeAction(reason, cb) { + Log.info( { eventName : this.name, action : this.action, reason : reason }, 'Executing scheduled event action...'); if('method' === this.action.type) { const modulePath = path.join(__dirname, '../', this.action.location); // enigma-bbs base + supplied location (path/file.js') @@ -158,14 +159,14 @@ function EventSchedulerModule(options) { const self = this; this.runningActions = new Set(); - this.performAction = function(schedEvent) { + this.performAction = function(schedEvent, reason) { if(self.runningActions.has(schedEvent.name)) { return; // already running } self.runningActions.add(schedEvent.name); - schedEvent.executeAction( () => { + schedEvent.executeAction(reason, () => { self.runningActions.delete(schedEvent.name); }); }; @@ -187,14 +188,14 @@ EventSchedulerModule.loadAndStart = function(cb) { const modInst = new mod.getModule(); modInst.startup( err => { - return cb(err); + return cb(err, modInst); }); }); }; EventSchedulerModule.prototype.startup = function(cb) { - this.eventTimers = []; + this.eventTimers = []; const self = this; if(this.moduleConfig && _.has(this.moduleConfig, 'events')) { @@ -219,11 +220,20 @@ EventSchedulerModule.prototype.startup = function(cb) { if(schedEvent.schedule.sched) { this.eventTimers.push(later.setInterval( () => { - self.performAction(schedEvent); + self.performAction(schedEvent, 'Schedule'); }, schedEvent.schedule.sched)); } - - // :TODO: handle watchfile -> performAction + + if(schedEvent.schedule.watchFile) { + gaze(schedEvent.schedule.watchFile, (err, watcher) => { + // :TODO: should track watched files & stop watching @ shutdown + watcher.on('all', (watchEvent, watchedPath) => { + if(schedEvent.schedule.watchFile === watchedPath) { + self.performAction(schedEvent, `Watch file: ${watchedPath}`); + } + }); + }); + } }); } @@ -234,6 +244,6 @@ EventSchedulerModule.prototype.shutdown = function(cb) { if(this.eventTimers) { this.eventTimers.forEach( et => et.clear() ); } - + cb(null); };