facebook-batch
Version:
Gracefully batching facebook requests.
149 lines • 5.38 kB
JavaScript
;
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());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const messaging_api_messenger_1 = require("messaging-api-messenger");
const BatchRequestError_1 = __importDefault(require("./BatchRequestError"));
const MAX_BATCH_SIZE = 50;
const alwaysTrue = () => true;
class FacebookBatchQueue {
/**
*
* @param client - A MessengerClient or FacebookClient instance.
* @param options - Optional batch config.
*
* @example
*
* ```js
* const client = new MessengerClient();
* new FacebookBatchQueue(client);
*
* new FacebookBatchQueue(client, {
* delay: 3000,
* shouldRetry: () => true,
* retryTimes: 3,
* });
* ```
*/
constructor(clientConfig, options = {}) {
var _a, _b, _c, _d;
this.queue = [];
// TODO: we use messenger client here for now, but maybe we will replace it with some facebook base client
this.client = new messaging_api_messenger_1.MessengerClient(clientConfig);
this.delay = (_a = options.delay) !== null && _a !== void 0 ? _a : 1000;
this.shouldRetry = (_b = options.shouldRetry) !== null && _b !== void 0 ? _b : alwaysTrue;
this.retryTimes = (_c = options.retryTimes) !== null && _c !== void 0 ? _c : 0;
this.includeHeaders = (_d = options.includeHeaders) !== null && _d !== void 0 ? _d : true;
this.timeout = setTimeout(() => this.flush(), this.delay);
}
/**
* Pushes a facebook request into the queue.
*
* @param request - The request to be queued.
* @returns A promise resolves the response of the request.
*
* @example
*
* ```js
* await bq.push({
* method: 'POST',
* relativeUrl: 'me/messages',
* body: {
* messagingType: 'UPDATE',
* recipient: 'PSID',
* message: { text: 'Hello World' },
* },
* });
* //=> {
* // recipientId: '...',
* // messageId: '...',
* // }
* ```
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
push(request) {
const promise = new Promise((resolve, reject) => {
this.queue.push({ request, resolve, reject });
});
if (this.queue.length >= MAX_BATCH_SIZE) {
this.flush();
}
return promise;
}
/**
* Flushes the queue proactively.
*
* This queue has a timer to flush items at a time interval, so normally you don't need to call this method.
*
* @example
*
* ```js
* await bq.flush();
* ```
*/
flush() {
return __awaiter(this, void 0, void 0, function* () {
const items = this.queue.splice(0, MAX_BATCH_SIZE);
clearTimeout(this.timeout);
this.timeout = setTimeout(() => this.flush(), this.delay);
if (items.length < 1)
return;
try {
const responses = yield this.client.sendBatch(items.map((item) => item.request), {
includeHeaders: this.includeHeaders,
});
items.forEach(({ request, resolve, reject, retry = 0 }, i) => {
const response = responses[i];
if (response.code === 200) {
resolve(response.body);
return;
}
const err = {
response: response,
request,
};
if (retry < this.retryTimes && this.shouldRetry(err)) {
this.queue.push({ request, resolve, reject, retry: retry + 1 });
}
else {
reject(new BatchRequestError_1.default(err));
}
});
}
catch (err) {
items.forEach(({ request, resolve, reject, retry = 0 }) => {
if (retry < this.retryTimes && this.shouldRetry(err)) {
this.queue.push({ request, resolve, reject, retry: retry + 1 });
}
else {
reject(err);
}
});
}
});
}
/**
* Stops the internal timer.
*
* @example
*
* ```js
* bq.stop();
* ```
*/
stop() {
clearTimeout(this.timeout);
}
}
exports.default = FacebookBatchQueue;
//# sourceMappingURL=FacebookBatchQueue.js.map