@dazejs/framework
Version:
Daze.js - A powerful web framework for Node.js
147 lines • 5.72 kB
JavaScript
;
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