UNPKG

vvlad1973-telegram-framework

Version:
219 lines (165 loc) 4.71 kB
/** * @fileoverview Queue based sender worker for TelegramBot class * @author Vlad Vnukovskiy <vvlad1973@gmail.com> * * @package */ /** * @module sender */ 'use strict' //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 }); }