background-process-js
Version:
A set of util tools for create background process.
107 lines (106 loc) • 3.88 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Consumer = exports.Events = void 0;
const node_crypto_1 = require("node:crypto");
const node_events_1 = require("node:events");
var Events;
(function (Events) {
Events["STOP"] = "stop";
Events["DEAD"] = "dead";
Events["CATCH"] = "catch";
Events["FINISH"] = "finish";
Events["PROCESS"] = "process";
})(Events || (exports.Events = Events = {}));
class Consumer extends node_events_1.EventEmitter {
constructor(config) {
super();
this.config = config;
this.stopedProcess = 0;
this.processToStop = 0;
this.needStopProcess = false;
}
finish(scalingId, messages) {
this.emit(`${Events.FINISH}-${scalingId}`, messages);
}
dead(scalingId, messages) {
this.emit(`${Events.DEAD}-${scalingId}`, messages);
}
async stop() {
return new Promise((resolve) => {
this.emit(Events.STOP);
this.stopPromiseResolver = resolve;
});
}
async catch(err) {
this.emit(Events.CATCH, err);
await this.stop();
}
process(hook) {
this.on(Events.PROCESS, hook);
}
async poll(amount = 1) {
this.processToStop = amount;
this.needStopProcess = false;
this.once(Events.CATCH, console.error);
this.once(Events.STOP, () => {
this.needStopProcess = true;
});
const scalablePolling = this.scalablePolling.bind(this);
const scalablePollings = new Array(amount).fill(scalablePolling);
const pollPromises = scalablePollings.map(async (scalePoll) => {
const scalingId = (0, node_crypto_1.randomUUID)();
await scalePoll(scalingId);
});
await Promise.all(pollPromises);
}
considerStopedProcess() {
this.stopedProcess += 1;
if (this.processToStop === this.stopedProcess) {
this.stopPromiseResolver(null);
}
}
async scalablePolling(scalingId) {
if (this.needStopProcess) {
return this.considerStopedProcess();
}
let messages = [];
const deleteMessages = this.deleteMessages.bind(this);
const markAsDeadMessages = this.markAsDeadMessages.bind(this);
const scalablePolling = this.scalablePolling.bind(this, scalingId);
const isEmpty = (arr) => arr.length === 0;
const timeoutToPolling = (messages) => setTimeout(() => scalablePolling(messages), this.config.timeoutAfterEndingPollingInMilliseconds);
try {
if (this.config.continuouslyPolling) {
do {
messages = await this.getMessages();
if (this.needStopProcess)
break;
} while (isEmpty(messages));
if (this.needStopProcess) {
return this.considerStopedProcess();
}
}
else {
messages = await this.getMessages();
if (isEmpty(messages))
return;
}
this.once(`${Events.FINISH}-${scalingId}`, deleteMessages);
if (this.config.hasDeadQueue) {
this.once(`${Events.DEAD}-${scalingId}`, markAsDeadMessages);
}
const receivedMaxMessages = messages.length === this.config.maxReceivedMessages;
if (receivedMaxMessages) {
this.once(`${Events.FINISH}-${scalingId}`, scalablePolling);
}
else if (this.config.continuouslyPolling) {
this.once(`${Events.FINISH}-${scalingId}`, timeoutToPolling);
}
this.emit(Events.PROCESS, { messages, scalingId });
}
catch (error) {
this.catch(error);
}
}
}
exports.Consumer = Consumer;