jumbo-core
Version:
Modern lightweight fast enterprise level MVW framework for Node.js
160 lines • 5.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const $cluster = require("cluster");
const DEBUG_MODE = Jumbo.config.debugMode;
const WORKERS_COUNT = !Jumbo.config.clustering.numberOfWorkers
? require('os').cpus().length
: Jumbo.config.clustering.numberOfWorkers;
var ClusterCommands;
(function (ClusterCommands) {
ClusterCommands[ClusterCommands["Log"] = 0] = "Log";
ClusterCommands[ClusterCommands["BanIp"] = 1] = "BanIp";
ClusterCommands[ClusterCommands["NewSession"] = 2] = "NewSession";
ClusterCommands[ClusterCommands["WorkerReady"] = 3] = "WorkerReady";
ClusterCommands[ClusterCommands["ExitApp"] = 4] = "ExitApp";
ClusterCommands[ClusterCommands["RestartWorker"] = 5] = "RestartWorker";
})(ClusterCommands = exports.ClusterCommands || (exports.ClusterCommands = {}));
var ClusterExitCommands;
(function (ClusterExitCommands) {
ClusterExitCommands[ClusterExitCommands["Exit"] = 0] = "Exit";
ClusterExitCommands[ClusterExitCommands["Restart"] = 1] = "Restart";
})(ClusterExitCommands = exports.ClusterExitCommands || (exports.ClusterExitCommands = {}));
const istanceKey = Symbol.for("Jumbo.Cluster.Cluster");
let instance = global[istanceKey] || null;
class Cluster {
constructor() {
this.workers = [];
this.numberOfWorkerReady = 0;
this.masterHandlers = [];
if (new.target != ClusterActivator) {
throw new Error("You cannot call private constructor!");
}
}
static get instance() {
if (instance == null) {
global[istanceKey] = instance = Reflect.construct(Cluster, [], ClusterActivator);
}
return instance;
}
invoke(cmd, data = null) {
let msg = {
invokeAction: cmd,
invokeData: data
};
if ($cluster.isWorker) {
process.send(msg);
}
else {
for (let worker of this.workers) {
worker.send(msg);
}
}
}
initClustering() {
if ($cluster.isMaster) {
if (Jumbo.config.clustering && typeof Jumbo.config.clustering.numberOfWorkers == "number"
&& !DEBUG_MODE) {
for (let c = 0; c < WORKERS_COUNT; c++) {
this.fork();
}
this.on(ClusterCommands.WorkerReady, () => this.workerReady());
this.on(ClusterCommands.ExitApp, () => this.exitApp());
this.on(ClusterCommands.RestartWorker, event => this.restartWorker(event));
$cluster.on("exit", (worker, code, signal) => {
this.onExit(worker, code, signal);
}).on("message", (worker, message) => {
this.masterOnMessage(worker, message);
});
}
}
else {
process.on("message", (message) => {
this.workerOnMessage(message);
});
}
}
on(cmd, callback) {
let cmdHandlers = this.masterHandlers[cmd];
if (!cmdHandlers) {
cmdHandlers = (this.masterHandlers[cmd] = []);
}
cmdHandlers.push(callback);
}
onExit(worker, code, signal) {
Jumbo.Logging.Log.line(`Worker ${worker.id} exited with code: ${code == undefined ? (signal || "unknown") : code}`);
if (code == 0)
return;
setTimeout(() => {
Jumbo.Logging.Log.line(`Reforking worker ${worker.id}`);
this.fork(worker);
}, 1000);
}
fork(worker) {
if (!!worker) {
let oldWorkerId = this.workers.findIndex(w => w.id == worker.id);
this.workers.splice(oldWorkerId, 1);
}
let fork = $cluster.fork();
this.workers.push(fork);
return fork;
}
workerOnMessage(message) {
if (message.hasOwnProperty("exit")) {
process.exit(message["exit"]);
}
}
masterOnMessage(worker, message) {
const Log = Jumbo.Logging.Log;
Log.line("[Worker " + worker.id + "] sent message: " + JSON.stringify(message), Log.LogTypes.Std, Log.LogLevels.TalkativeCluster);
let handlers = this.masterHandlers[message.invokeAction];
if (handlers) {
let isDefaultPrevented = false;
let stopPropagation = false;
let event = {
worker: worker,
data: message.invokeData,
get isDefaultPrevented() {
return isDefaultPrevented;
},
preventDefault() {
isDefaultPrevented = true;
},
stopPropagation() {
stopPropagation = true;
}
};
let i = 0;
while (i < handlers.length && !stopPropagation) {
handlers[i++](event);
}
}
else {
Log.warning("Not handled cluster message (code " + message.invokeAction + ").");
}
}
workerReady() {
this.numberOfWorkerReady++;
if (this.numberOfWorkerReady == WORKERS_COUNT) {
Jumbo.Application.Application.instance.workersReady();
}
}
exitApp() {
Jumbo.Application.Application.exit();
}
restartWorker(event) {
let worker = event.worker;
this.fork().on("online", () => {
setTimeout(() => {
try {
worker.send({ exit: 0 });
}
catch (e) { }
}, 1000);
});
}
}
exports.Cluster = Cluster;
class ClusterActivator extends Cluster {
}
exports.cluster = Cluster.instance;
//# sourceMappingURL=Cluster.js.map