UNPKG

pandora

Version:
248 lines 8.88 kB
'use strict'; 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