UNPKG

@dazejs/framework

Version:

Daze.js - A powerful web framework for Node.js

147 lines 5.72 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Master = void 0; const cluster_1 = __importDefault(require("cluster")); const debug_1 = __importDefault(require("debug")); const net_1 = __importDefault(require("net")); const string_hash_1 = __importDefault(require("string-hash")); const defered_1 = require("../utils/defered"); const const_1 = require("./const"); const helpers_1 = require("./helpers"); const debug = (0, debug_1.default)('daze-framework:cluster'); const defaultOptions = { port: 0, workers: 0, sticky: false, }; class Master { constructor(opts) { this.connections = {}; this.options = Object.assign({}, defaultOptions, (0, helpers_1.parseMasterOpts)(opts)); } forkWorker(env = {}) { const worker = cluster_1.default.fork(env); debug(`worker is forked, use pid: ${worker.process.pid}`); worker[const_1.DAZE_PROCESS_TYPE] = 'worker'; const deferred = new defered_1.Deferred(); worker.on('message', (message) => { if (Reflect.getMetadata(const_1.WORKER_DYING, worker)) return; if (message === const_1.WORKER_DISCONNECT) { debug('refork worker, receive message \'daze-worker-disconnect\''); Reflect.defineMetadata(const_1.WORKER_DYING, true, worker); this.forkWorker(env).then(() => worker.send(const_1.WORKER_DID_FORKED)).catch(() => { }); } }); worker.once('disconnect', () => { if (Reflect.getMetadata(const_1.WORKER_DYING, worker)) return; debug(`worker disconnect: ${worker.process.pid}`); Reflect.defineMetadata(const_1.WORKER_DYING, true, worker); debug('worker will fork'); this.forkWorker(env); }); worker.once('exit', (code, signal) => { if (Reflect.getMetadata(const_1.WORKER_DYING, worker)) return; debug(`worker exit, code: ${code}, signal: ${signal}`); Reflect.defineMetadata(const_1.WORKER_DYING, true, worker); this.forkWorker(env); }); worker.once('listening', (address) => { debug(`listening, address: ${JSON.stringify(address)}`); deferred.resolve(worker); }); return deferred.promise; } forkWorkers() { const { workers } = this.options; const promises = []; const env = { DAZE_PROCESS_TYPE: 'worker' }; for (let i = 0; i < workers; i += 1) { promises.push(this.forkWorker(env)); } return Promise.all(promises); } forkAgent() { const env = { DAZE_PROCESS_TYPE: 'agent' }; const agent = cluster_1.default.fork(env); agent[const_1.DAZE_PROCESS_TYPE] = 'agent'; agent.once('disconnect', () => { if (Reflect.getMetadata(const_1.WORKER_DYING, agent)) return; debug(`agent disconnect: ${agent.process.pid}`); Reflect.defineMetadata(const_1.WORKER_DYING, true, agent); debug('agent will fork'); this.forkAgent(); }); agent.once('exit', (code, signal) => { if (Reflect.getMetadata(const_1.WORKER_DYING, agent)) return; debug(`agent exit, code: ${code}, signal: ${signal}`); Reflect.defineMetadata(const_1.WORKER_DYING, true, agent); cluster_1.default.fork(env); }); } cteateStickyServer() { const deferred = new defered_1.Deferred(); const server = net_1.default.createServer({ pauseOnConnect: true }, (connection) => { const signature = `${connection.remoteAddress}:${connection.remotePort}`; this.connections[signature] = connection; connection.on('close', () => { delete this.connections[signature]; }); const index = (0, string_hash_1.default)(connection.remoteAddress || '') % this.options.workers; let current = -1; (0, helpers_1.getAlivedWorkers)().some((worker) => { if (index === ++current) { worker.send(const_1.STIKCY_CONNECTION, connection); return true; } return false; }); }); server.listen(this.options.port, () => { this.forkWorkers().then((data) => { deferred.resolve(data); }); }); return deferred.promise; } reloadWorkers() { for (const worker of (0, helpers_1.getAlivedWorkers)()) { worker.send(const_1.RELOAD_SIGNAL); } return this; } catchSignalToReload() { process.once(const_1.RELOAD_SIGNAL, () => { debug(`Start smooth restart, signal: ${const_1.RELOAD_SIGNAL}`); this.reloadWorkers(); }); cluster_1.default.on('message', (_worker, message) => { if (message !== 'daze-restart') return; this.reloadWorkers(); }); } async run() { debug(`current master process id [${process.pid}]`); const serverPromise = this.options.sticky ? this.cteateStickyServer() : this.forkWorkers(); const workers = serverPromise.then((res) => { this.catchSignalToReload(); return res; }); return workers; } } exports.Master = Master; //# sourceMappingURL=master.js.map