vvlad1973-telegram-framework
Version:
Current version: *7.9.5*
219 lines (165 loc) • 4.71 kB
JavaScript
/**
* @fileoverview Queue based sender worker for TelegramBot class
* @author Vlad Vnukovskiy <vvlad1973@gmail.com>
*
* @package
*/
/**
* @module sender
*/
//TODO: It's need to refactoring sender, change doing iterations from while
//loop to setInterval initiation
import { parentPort, workerData } from 'worker_threads';
import got from 'got';
import Queue from 'vvlad1973-queue';
import { createFormData, getGotInstance, sendPostRequest } from '../../helpers/utils.js';
import { StatusCodes, TelegramBotApiMethods } from '../enums.js';
import { TELEGRAM_BOT_API_URL } from '../../helpers/definitions.js';
const queue = new Queue(workerData.queue.size);
const instance = getGotInstance();
let
capacity = workerData.capacity,
error429 = workerData.error429 ?? { descriptionPattern: '.*retry after (\\d+)', maxWaitingTime: 5000, maxResendAttepmts: 10 },
apiUrl = workerData.url,
counter = {
dateTime: 0,
count: 0
};
function doTask(task) {
return new Promise(async (resolve, reject) => {
let
options = {},
result,
response,
url = task.data.payload.token ? `${TELEGRAM_BOT_API_URL}${task.data.payload.token}/` : apiUrl;
try {
if (task.data.multipart) {
let form = createFormData(task.data.payload);
options.headers = form.getHeaders();
options.body = form;
} else {
options.json = task.data.payload;
delete options.json.token;
}
options.responseType = 'json';
try {
response = await sendPostRequest(url, options, instance);
} catch (error) {
response = error;
}
if (typeof response === 'object') {
response.queue_size = queue.size;
if (typeof response.request === 'object') response.request.id = task.id;
}
resolve(response);
return response;
} catch (error) {
reject(error);
}
});
}
parentPort.on('message', request => {
if (typeof request === 'object' && typeof request.data.payload.method === 'string') {
if (Object.values(TelegramBotApiMethods).includes(request.data.payload.method)) {
let priority;
switch (request.data.payload.method) {
case TelegramBotApiMethods.ANSWER_CALLBACK_QUERY:
priority = 1;
break;
default:
priority = 2;
break;
}
queue.enqueue(request, priority)
.catch(error => {
logError({
result: {
ok: false,
code: StatusCodes.INTERNAL_SERVER_ERROR
},
error: error,
request: request,
queue: queue.contents
})
})
} else {
logError({
result: {
ok: false,
code: StatusCodes.NOT_IMPLEMENTED
},
error: {
message: `Method ${request.data.payload.method} is not implemented`
},
request: request
});
}
} else if (typeof request === 'object' && request.command) {
} else {
logError({
result: {
ok: false,
code: StatusCodes.BAD_REQUEST
},
error: {
message: 'Invalid format of data'
},
request: request
});
}
});
setInterval(() => {
counter.dateTime = Date.now();
counter.count = 0;
}, capacity.interval);
while (true) {
let
now = Date.now(),
delay = (counter.count === capacity.limit) ? (capacity.interval - (now - counter.dateTime)) : 0;
await (() => {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
}, delay)
})
})();
let task = await queue.dequeue();
if (task) {
doTask(task)
.then(result => {
parentPort.postMessage(JSON.parse(JSON.stringify(result)));
})
.catch(error => {
logError({
result: {
ok: false,
code: error.code
},
error: error,
request: task
})
});
counter.count++;
}
}
function logTrace(message) {
if (message)
parentPort.postMessage({ trace: message });
}
function logDebug(message) {
if (message)
parentPort.postMessage({ debug: message });
}
function logError(error) {
if (error)
parentPort.postMessage({ error: error });
}
function logWarn(message) {
if (message)
parentPort.postMessage({ warn: message });
}
function logInfo(message) {
if (message)
parentPort.postMessage({ info: message });
}