occaecatidicta
Version:
149 lines (132 loc) • 5.68 kB
text/typescript
import * as starter from './starter';
import { getLogger } from 'omelox-logger';
import * as path from 'path';
let logger = getLogger('omelox', path.basename(__filename));
let crashLogger = getLogger('crash-log', path.basename(__filename));
let adminLogger = getLogger('admin-log', path.basename(__filename));
import * as admin from 'omelox-admin';
import * as util from 'util';
import * as utils from '../util/utils';
import * as moduleUtil from '../util/moduleUtil';
import * as Constants from '../util/constants';
import { Application } from '../application';
import { ConsoleService, ConsoleServiceOpts } from 'omelox-admin';
import { IModule } from '../index';
export type MasterServerOptions =
{
port?: number;
env?: string;
closeWatcher?: boolean;
} & Partial<ConsoleServiceOpts>;
export class MasterServer {
app: Application;
masterInfo: any;
registered = {};
modules: IModule[] = [];
closeWatcher: boolean;
masterConsole: ConsoleService;
constructor(app: Application, opts?: MasterServerOptions) {
this.app = app;
this.masterInfo = app.getMaster();
opts = opts || {};
opts.port = this.masterInfo.port;
opts.env = this.app.get(Constants.RESERVED.ENV);
this.closeWatcher = opts.closeWatcher || false;
this.masterConsole = admin.createMasterConsole(opts);
}
start(cb: (err?: Error) => void) {
moduleUtil.registerDefaultModules(true, this.app, this.closeWatcher);
moduleUtil.loadModules(this, this.masterConsole);
let self = this;
// start master console
this.masterConsole.start(function (err) {
if (err) {
process.exit(0);
}
moduleUtil.startModules(self.modules, function (err: Error) {
if (err) {
utils.invokeCallback(cb, err);
return;
}
if (self.app.get(Constants.RESERVED.MODE) !== Constants.RESERVED.STAND_ALONE) {
starter.runServers(self.app);
}
utils.invokeCallback(cb);
});
});
this.masterConsole.on('error', function (err) {
if (!!err) {
logger.error('masterConsole encounters with error: ' + err.stack);
return;
}
});
this.masterConsole.on('reconnect', function (info) {
self.app.addServers([info]);
});
// monitor servers disconnect event
this.masterConsole.on('disconnect', function (id, type, info, reason) {
crashLogger.info(util.format('[%s],[%s],[%s],[%s]', type, id, Date.now(), reason || 'disconnect'));
let count = 0;
let time = 0;
let pingTimer: NodeJS.Timer = null;
let server = self.app.getServerById(id);
let stopFlags = self.app.get(Constants.RESERVED.STOP_SERVERS) || [];
let autoRestart: any = server && server[Constants.RESERVED.AUTO_RESTART] || '';
let restartForce: any = server && server[Constants.RESERVED.RESTART_FORCE] || '';
if ((autoRestart.toString() === 'true' || restartForce.toString() === 'true') && stopFlags.indexOf(id) < 0) {
let handle = function () {
clearTimeout(pingTimer);
utils.checkPort(server, function (status) {
if (status === 'error') {
utils.invokeCallback(cb, new Error('Check port command executed with error.'));
return;
} else if (status === 'busy') {
if (!!server[Constants.RESERVED.RESTART_FORCE]) {
starter.kill([info.pid], [server]);
} else {
utils.invokeCallback(cb, new Error('Port occupied already, check your server to add.'));
return;
}
}
setTimeout(function () {
starter.run(self.app, server, null);
}, Constants.TIME.TIME_WAIT_STOP);
});
};
let setTimer = function (time: number) {
pingTimer = setTimeout(function () {
utils.ping(server.host, function (flag) {
if (flag) {
handle();
} else {
count++;
if (count > 3) {
time = Constants.TIME.TIME_WAIT_MAX_PING;
} else {
time = Constants.TIME.TIME_WAIT_PING * count;
}
setTimer(time);
}
});
}, time);
};
setTimer(time);
}
});
// monitor servers register event
this.masterConsole.on('register', function (record) {
starter.bindCpu(record.id, record.pid, record.host);
});
this.masterConsole.on('admin-log', function (log, error) {
if (error) {
adminLogger.error(JSON.stringify(log));
} else {
adminLogger.info(JSON.stringify(log));
}
});
}
stop(cb: () => void) {
this.masterConsole.stop();
process.nextTick(cb);
}
}