UNPKG

firewalk

Version:

A collection traversal library for Firestore

107 lines 7.11 kB
"use strict"; 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 __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _PromiseQueueBasedTraverserImpl_instances, _a, _PromiseQueueBasedTraverserImpl_defaultConfig, _PromiseQueueBasedTraverserImpl_makeRetriableAccordingToConfig, _PromiseQueueBasedTraverserImpl_getProcessableItemCount, _PromiseQueueBasedTraverserImpl_getProcessQueueInterval; Object.defineProperty(exports, "__esModule", { value: true }); exports.PromiseQueueBasedTraverserImpl = void 0; const errors_1 = require("../../errors"); const errors_2 = require("../errors"); const ds_1 = require("../ds"); const utils_1 = require("../utils"); const abstract_1 = require("./abstract"); class PromiseQueueBasedTraverserImpl extends abstract_1.AbstractTraverser { constructor(traversable, exitEarlyPredicates = [], config) { super(Object.assign(Object.assign({}, __classPrivateFieldGet(_a, _a, "f", _PromiseQueueBasedTraverserImpl_defaultConfig)), config), exitEarlyPredicates); _PromiseQueueBasedTraverserImpl_instances.add(this); this.traversable = traversable; } withConfig(config) { return new _a(this.traversable, this.exitEarlyPredicates, Object.assign(Object.assign({}, this.traversalConfig), config)); } withExitEarlyPredicate(predicate) { return new _a(this.traversable, [...this.exitEarlyPredicates, predicate], this.traversalConfig); } traverse(callback) { return __awaiter(this, void 0, void 0, function* () { const { traversalConfig } = this; const { maxConcurrentBatchCount } = traversalConfig; callback = __classPrivateFieldGet(this, _PromiseQueueBasedTraverserImpl_instances, "m", _PromiseQueueBasedTraverserImpl_makeRetriableAccordingToConfig).call(this, callback); if (maxConcurrentBatchCount === 1) { return this.runTraversal((batchDocs, batchIndex) => __awaiter(this, void 0, void 0, function* () { yield callback(batchDocs, batchIndex); })); } const callbackPromiseQueue = new ds_1.PromiseQueue(); const unregisterQueueProcessor = (0, utils_1.registerInterval)(() => __awaiter(this, void 0, void 0, function* () { if (!callbackPromiseQueue.isProcessing) { const processableItemCount = __classPrivateFieldGet(this, _PromiseQueueBasedTraverserImpl_instances, "m", _PromiseQueueBasedTraverserImpl_getProcessableItemCount).call(this, callbackPromiseQueue.size); try { yield callbackPromiseQueue.processFirst(processableItemCount); } catch (err) { throw err instanceof errors_2.IllegalArgumentError ? new errors_1.ImplementationError(`Encountered an expected error originating from an incorrectly implemented PromiseQueue data structure.`) : err; } } }), () => __classPrivateFieldGet(this, _PromiseQueueBasedTraverserImpl_instances, "m", _PromiseQueueBasedTraverserImpl_getProcessQueueInterval).call(this, callbackPromiseQueue.size)); const traversalResult = yield this.runTraversal((batchDocs, batchIndex) => { var _b; callbackPromiseQueue.enqueue((_b = callback(batchDocs, batchIndex)) !== null && _b !== void 0 ? _b : Promise.resolve()); return () => __awaiter(this, void 0, void 0, function* () { while (callbackPromiseQueue.size >= maxConcurrentBatchCount) { // TODO: There probably is a better way to compute sleep duration const processQueueInterval = __classPrivateFieldGet(this, _PromiseQueueBasedTraverserImpl_instances, "m", _PromiseQueueBasedTraverserImpl_getProcessQueueInterval).call(this, callbackPromiseQueue.size); yield (0, utils_1.sleep)(processQueueInterval); } }); }); yield unregisterQueueProcessor(); // There may still be some Promises left in the queue but there won't be any new ones coming in. // Wait for the existing ones to resolve and exit. yield callbackPromiseQueue.processAll(); return traversalResult; }); } } exports.PromiseQueueBasedTraverserImpl = PromiseQueueBasedTraverserImpl; _a = PromiseQueueBasedTraverserImpl, _PromiseQueueBasedTraverserImpl_instances = new WeakSet(), _PromiseQueueBasedTraverserImpl_makeRetriableAccordingToConfig = function _PromiseQueueBasedTraverserImpl_makeRetriableAccordingToConfig(callback) { const { maxBatchRetryCount, sleepTimeBetweenTrials } = this.traversalConfig; let cb = callback; if (maxBatchRetryCount > 0) { const retriableCallback = (0, utils_1.makeRetriable)(callback, { maxTrialCount: 1 + maxBatchRetryCount, sleepTimeBetweenTrials, returnErrors: true, }); cb = (...args) => __awaiter(this, void 0, void 0, function* () { const result = yield retriableCallback(...args); if (!result.hasSucceeded) { const { errors } = result; const lastError = errors[errors.length - 1]; throw lastError; } }); } return cb; }, _PromiseQueueBasedTraverserImpl_getProcessableItemCount = function _PromiseQueueBasedTraverserImpl_getProcessableItemCount(queueSize) { // TODO: Implement using traversal config and queue size return queueSize; }, _PromiseQueueBasedTraverserImpl_getProcessQueueInterval = function _PromiseQueueBasedTraverserImpl_getProcessQueueInterval(queueSize) { // TODO: Implement using traversal config and queue size return 250; }; _PromiseQueueBasedTraverserImpl_defaultConfig = { value: Object.assign({}, abstract_1.AbstractTraverser.baseConfig) }; //# sourceMappingURL=PromiseQueueBasedTraverserImpl.js.map