@shahadul-17/dispatcher
Version:
Defines a mechanism for parallel processing and CPU intensive tasks in Node.js
102 lines • 4.6 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ParentProcess = void 0;
const utilities_1 = require("@shahadul-17/utilities");
const event_manager_1 = require("@shahadul-17/event-manager");
const process_event_type_e_1 = require("./process-event-type.e");
const END_OF_DATA_MARKER = "<--- END OF DATA --->";
/**
* Child processes shall use this class to communicate with the parent process.
*/
class ParentProcess extends event_manager_1.EventManager {
constructor(options) {
super();
this._taskCount = 0;
this._options = options;
this._options.commandLineArguments = utilities_1.ArgumentsParser.toObject();
this._options.processId = parseInt(this._options.commandLineArguments.processId);
this.streamReader = new utilities_1.StreamReader();
this.streamReader.setLineDelimiter(END_OF_DATA_MARKER);
// binding methods...
this.incrementTaskCount = this.incrementTaskCount.bind(this);
this.decrementTaskCount = this.decrementTaskCount.bind(this);
this.onDataReceivedAsync = this.onDataReceivedAsync.bind(this);
this.spawnAsync = this.spawnAsync.bind(this);
this.sendAsync = this.sendAsync.bind(this);
}
get isChildProcess() { return true; }
get taskCount() { return this._taskCount; }
get processId() { return this.options.processId; }
get options() { return this._options; }
incrementTaskCount(step) {
// if the provided step is not a positive number...
if (!utilities_1.NumberUtilities.isPositiveNumber(step)) {
// we shall set the step to 1...
step = 1;
}
this._taskCount = this._taskCount + step;
return this._taskCount;
}
decrementTaskCount(step) {
// if the provided step is not a positive number...
if (!utilities_1.NumberUtilities.isPositiveNumber(step)) {
// we shall set the step to 1...
step = 1;
}
this._taskCount = this._taskCount - step;
// task count can never be less than zero...
if (this._taskCount < 0) {
this._taskCount = 0;
}
return this._taskCount;
}
onDataReceivedAsync(chunk) {
return __awaiter(this, void 0, void 0, function* () {
this.streamReader.append(chunk);
let data;
while (utilities_1.ObjectUtilities.isObject(data = this.streamReader.readObject())) {
// dispatches data receive event...
this.dispatchEventListeners({
type: process_event_type_e_1.ProcessEventType.DataReceive,
data: data,
});
}
});
}
spawnAsync() {
return new Promise((resolve) => __awaiter(this, void 0, void 0, function* () {
process.stdin.setEncoding("utf-8");
process.stdin.on("data", chunk => this.onDataReceivedAsync(chunk));
this.dispatchEventListeners({
type: process_event_type_e_1.ProcessEventType.Spawn,
processId: this.processId,
});
resolve(this);
}));
}
sendAsync(data) {
return __awaiter(this, void 0, void 0, function* () {
// any error thrown by this method shall be sent to the parent...
let dataAsJson = utilities_1.JsonSerializer.serialize(data, {
shallDeepSanitize: true,
});
dataAsJson = `${dataAsJson}${END_OF_DATA_MARKER}\n`; // <-- we must add the new-line character...
// we shall send data to the parent process...
process.stdout.cork();
const isSent = process.stdout.write(dataAsJson, "utf-8");
process.stdout.uncork();
return isSent;
});
}
}
exports.ParentProcess = ParentProcess;
//# sourceMappingURL=parent-process.js.map