airship-server
Version:
Airship is a framework for Node.JS & TypeScript that helps you to write big, scalable and maintainable API servers.
165 lines • 8.06 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const VKApiError_1 = require("../../vkApi/VKApiError");
/**
* HHEventsNotificationsSender sends output messages in 25 item batches
*/
class HHEventsNotificationsSender {
constructor(tokensProvider, outputMessagesProvider, outputMessageSender, bannedEndpointsCache, logger) {
this._tokensProvider = tokensProvider;
this._outputMessagesProvider = outputMessagesProvider;
this._outputMessageSender = outputMessageSender;
this._bannedEndpointsCache = bannedEndpointsCache;
this._logger = logger;
this._groupsMessagesQueues = [];
this._groupsTimeouts = [];
this._outputMessagesProvider.getMessages((outputMessage, ack) => {
this.handleMessage(outputMessage, ack);
});
}
handleMessage(message, ack) {
return __awaiter(this, void 0, void 0, function* () {
let isEmpty = this._outputMessageSender.isEmpty(message);
if (isEmpty) {
console.log('Empty message', message);
ack();
return;
}
let isBannedGroup = yield this._bannedEndpointsCache.get(message.groupId * -1);
let isBannedUser = yield this._bannedEndpointsCache.get(message.userId);
if (isBannedGroup) {
this._logger.warn(`Group ${message.groupId} is banned`);
ack();
return;
}
if (isBannedUser) {
this._logger.warn(`No permissions to send to user ${message.userId}`);
ack();
return;
}
if (!this._groupsMessagesQueues[message.groupId])
this._groupsMessagesQueues[message.groupId] = [];
this._groupsMessagesQueues[message.groupId].push({ message, ack });
if (this._groupsMessagesQueues[message.groupId].length == 1) {
this._groupsTimeouts[message.groupId] = setTimeout(() => {
clearTimeout(this._groupsTimeouts[message.groupId]);
this._groupsTimeouts[message.groupId] = null;
let batch = this._groupsMessagesQueues[message.groupId].slice(0, 25);
this._groupsMessagesQueues[message.groupId] = this._groupsMessagesQueues[message.groupId].slice(25);
this.sendByTimeout(batch);
}, 600);
}
else if (this._groupsMessagesQueues[message.groupId].length >= 25) {
let batch = this._groupsMessagesQueues[message.groupId].slice(0, 25);
this._groupsMessagesQueues[message.groupId] = this._groupsMessagesQueues[message.groupId].slice(25);
clearTimeout(this._groupsTimeouts[message.groupId]);
this._groupsTimeouts[message.groupId] = null;
let token = yield this._tokensProvider.getToken(message);
yield this.sendBatch(batch, token);
}
});
}
sendByTimeout(messages) {
return __awaiter(this, void 0, void 0, function* () {
let token = yield this._tokensProvider.getToken(messages[0].message);
yield this.sendBatch(messages, token);
});
}
sendBatch(messages, token) {
return __awaiter(this, void 0, void 0, function* () {
function retry(message, ack) {
setTimeout(() => {
this.handleMessage(message, ack);
}, 1000);
}
try {
let response = yield this._outputMessageSender.sendBatch(messages.map(m => m.message), token);
if (response['execute_errors']) {
let errorIndex = 0;
let i = 0;
for (let responseCode of response['response']) {
// vk api sometimes returns 0 for some reason
if (responseCode === false) {
let error = response['execute_errors'][errorIndex];
if (error['error_code'] == 6 ||
//error['error_code'] == 9 ||
error['error_code'] == 10) {
retry.bind(this)(messages[i].message, messages[i].ack);
}
else if (error['error_code'] == 901) {
// no permissions to send to user
this._logger.warn(`no permissions to send to user userId: ${messages[i].message.userId} groupId: ${messages[i].message.groupId}`);
//await this._bannedEndpointsCache.cache(messages[i].message.userId, true, 1000 * 60 * 5)
messages[i].ack();
}
else if (error['error_code'] == 5) {
// group is banned
yield this._bannedEndpointsCache.cache(messages[i].message.groupId * -1, true, 1000 * 60 * 60);
messages[i].ack();
}
else {
messages[i].ack();
}
errorIndex++;
}
else {
messages[i].ack();
}
i++;
}
}
else {
for (let i = 0; i <= response['response'].length - 1; i++) {
messages[i].ack();
}
}
}
catch (e) {
console.log(e);
if (e.message == 'no messages to send') {
for (let i = 0; i <= messages.length - 1; i++) {
messages[i].ack();
}
}
else if (e instanceof VKApiError_1.default) {
if (e.errorCode == 6) {
setTimeout(() => {
for (let i = 0; i <= messages.length - 1; i++) {
this.handleMessage(messages[i].message, messages[i].ack);
}
//this.sendBatch(messages, token)
}, 300);
}
else if (e.errorCode == 5) {
yield this._bannedEndpointsCache.cache(messages[0].message.groupId * -1, true, 1000 * 60 * 60);
for (let i = 0; i <= messages.length - 1; i++) {
messages[i].ack();
}
}
else {
this._logger.error('Strange vk bug');
for (let i = 0; i <= messages.length - 1; i++) {
messages[i].ack();
}
}
}
else {
this._logger.error('Very bad bug');
for (let i = 0; i <= messages.length - 1; i++) {
messages[i].ack();
}
}
}
});
}
}
exports.default = HHEventsNotificationsSender;
//# sourceMappingURL=HHEventsNotificationsSender.js.map