pandora
Version:
248 lines • 8.88 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const ComplexHandler_1 = require("./ComplexHandler");
const Base = require("sdk-base");
const const_1 = require("../const");
const fs = require("fs");
const assert = require("assert");
const pandora_messenger_1 = require("pandora-messenger");
const LoggerBroker_1 = require("../universal/LoggerBroker");
const Monitor_1 = require("../monitor/Monitor");
const daemonLogger = LoggerBroker_1.getDaemonLogger();
var State;
(function (State) {
State[State["pending"] = 1] = "pending";
State[State["complete"] = 2] = "complete";
State[State["stopped"] = 3] = "stopped";
})(State || (State = {}));
/**
* Class Daemon
*/
class Daemon extends Base {
constructor() {
super();
this.state = State.pending;
this.apps = new Map();
}
/**
* Start Daemon
* @return {Promise<any>}
*/
start() {
return __awaiter(this, void 0, void 0, function* () {
if (this.state === State.complete) {
return;
}
return new Promise((resolve, reject) => {
this.messengerServer = pandora_messenger_1.default.getServer({
name: const_1.DAEMON_MESSENGER,
});
this.messengerServer.on(const_1.SEND_DAEMON_MESSAGE, (message, reply) => {
this.handleCommand(message, reply);
});
this.messengerServer.ready(() => {
return this.startMonitor().then(() => {
this.state = State.complete;
this.ready(true);
resolve();
}).catch(err => {
daemonLogger.error(err);
process.exit(1);
reject(err);
});
});
this.handleExit();
});
});
}
/**
* Handing all passive exit events, such as process signal, uncaughtException
*/
handleExit() {
process.on('uncaughtException', (err) => {
daemonLogger.error(err);
this.stop();
});
// SIGTERM AND SIGINT will trigger the exit event.
['SIGQUIT', 'SIGTERM', 'SIGINT'].forEach(sig => {
process.once(sig, () => {
this.stop();
});
});
process.once('exit', () => {
this.stop();
});
}
/**
* Handle daemon's command invocations
* @param message
* @param reply
*/
handleCommand(message, reply) {
const command = message.command;
const args = message.args;
switch (command) {
case 'start':
this.startApp(args).then(() => {
reply({ data: `${args.appName} started successfully! log file: ${LoggerBroker_1.getAppLogPath(args.appName, 'nodejs_stdout')}` });
}).catch(err => {
reply({ error: `${args.appName} started failed, ${err && err.toString()}` });
});
break;
case 'stopAll':
this.stopAllApps().then(() => {
reply({ data: `all apps stopped successfully!` });
}).catch(err => {
reply({ error: `all apps stopped failed, ${err && err.toString()}` });
});
break;
case 'stopApp':
this.stopApp(args.appName).then(() => {
reply({ data: `${args.appName} stopped successfully!` });
}).catch(err => {
reply({ error: `${args.appName} stopped failed, ${err && err.toString()}` });
});
break;
case 'restart':
this.stopApp(args.appName).then(diedApp => {
return this.startApp(diedApp.appRepresentation);
}).then(() => {
reply({ data: `${args.appName} restarted successfully!` });
}).catch(err => {
reply({ error: `${args.appName} restarted failed, ${err && err.toString()}` });
});
break;
case 'exit':
this.stop().then(() => {
process.exit(0);
});
break;
case 'list':
const keySet = Array.from(this.apps.keys());
const data = keySet.map((key) => {
const complex = this.apps.get(key);
return {
name: complex.name,
appId: complex.appId,
pids: complex.pids,
mode: complex.mode,
appDir: complex.appDir,
state: complex.state
};
});
reply({ data: data });
break;
}
}
/**
* Start an application
*
* @param {ApplicationRepresentation} applicationRepresentation
* @returns {Promise<ComplexHandler>}
*/
startApp(applicationRepresentation) {
return __awaiter(this, void 0, void 0, function* () {
// require appName and appDir when app start
const appName = applicationRepresentation.appName;
const appDir = applicationRepresentation.appDir;
assert(appName, `options.appName is required!`);
assert(appDir, `options.appDir is required!`);
assert(fs.existsSync(appDir), `${appDir} does not exists!`);
assert(!this.apps.has(appName), `app[${appName}] has been initialized!`);
const complexHandler = new ComplexHandler_1.ComplexHandler(applicationRepresentation);
yield complexHandler.start();
this.apps.set(appName, complexHandler);
return complexHandler;
});
}
/**
* Reload an application
* @param appName
* @param processName
* @return {Promise<ComplexHandler>}
*/
reloadApp(appName, processName) {
return __awaiter(this, void 0, void 0, function* () {
const complex = this.apps.get(appName);
if (!complex) {
throw new Error(`${appName} does not exists!`);
}
yield complex.reload(processName);
return complex;
});
}
/**
* stop an application
* @param appName
* @return {Promise<ComplexHandler>}
*/
stopApp(appName) {
return __awaiter(this, void 0, void 0, function* () {
const complex = this.apps.get(appName);
if (!complex) {
throw new Error(`${appName} does not exists!`);
}
yield complex.stop();
this.apps.delete(appName);
return complex;
});
}
/**
* stop all the applications
* @return {Promise<void>}
*/
stopAllApps() {
return __awaiter(this, void 0, void 0, function* () {
for (const appName of this.apps.keys()) {
yield this.stopApp(appName);
}
});
}
/**
* stop an application
* @return {Promise<void>}
*/
stop() {
return __awaiter(this, void 0, void 0, function* () {
this.state = State.stopped;
yield this.stopAllApps();
daemonLogger.info('daemon is going to stop');
this.messengerServer.close();
yield this.stopMonitor();
this.state = State.stopped;
});
}
/**
* Start the monitor
* @return {Promise<void>}
*/
startMonitor() {
return __awaiter(this, void 0, void 0, function* () {
if (!this.monitor) {
this.monitor = new Monitor_1.Monitor();
}
return this.monitor.start();
});
}
/**
* Stop the monitor
* @return {Promise<void>}
*/
stopMonitor() {
return __awaiter(this, void 0, void 0, function* () {
if (this.monitor) {
return this.monitor.stop();
}
});
}
}
exports.Daemon = Daemon;
//# sourceMappingURL=Daemon.js.map