UNPKG

jinaga

Version:

Data management for web and mobile applications.

138 lines 4.41 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()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.QueueProcessor = void 0; const trace_1 = require("../util/trace"); class Batch { constructor(saver, delayMilliseconds, setBatch) { this.saver = saver; this.delayMilliseconds = delayMilliseconds; this.setBatch = setBatch; this.isActive = false; this.hasWork = false; this.isTerminated = false; this.delay = null; this.nextBatch = null; this.notifyResolver = null; this.notifyRejector = null; this.notifyPromise = null; } activate() { this.isActive = true; this.beginWaiting(); } workArrived() { this.hasWork = true; this.beginWaiting(); } runNow() { if (this.isTerminated) { return Promise.resolve(); } if (!this.notifyPromise) { this.notifyPromise = new Promise((resolve, reject) => { this.notifyResolver = resolve; this.notifyRejector = reject; }); this.beginWorking(); } return this.notifyPromise; } terminate() { this.isTerminated = true; if (this.delay) { clearTimeout(this.delay); this.delay = null; } if (this.notifyRejector) { this.notifyRejector(new Error("QueueProcessor terminated")); } } beginWaiting() { if (this.isTerminated || !this.isActive || !this.hasWork || this.delay) { return; } if (this.delayMilliseconds === 0) { this.beginWorking(); } else { this.delay = setTimeout(() => { this.beginWorking(); }, this.delayMilliseconds); } } beginWorking() { if (this.nextBatch) { return; } this.nextBatch = new Batch(this.saver, this.delayMilliseconds, this.setBatch); this.setBatch(this.nextBatch); this.saver.save() .then(() => this.done(null)) .catch((error) => this.done(error)); } done(error) { if (this.notifyResolver) { if (error) { this.notifyRejector(error); } else { this.notifyResolver(); } } else if (error) { trace_1.Trace.error(error); } if (this.nextBatch) { this.nextBatch.activate(); } } } /** * Processes a queue with a debouncing mechanism. * This improves performance by batching multiple operations together. */ class QueueProcessor { /** * Creates a new QueueProcessor. * @param saver The component that will save the data. * @param delayMilliseconds The delay in milliseconds before processing the queue. */ constructor(saver, delayMilliseconds) { this.currentBatch = new Batch(saver, delayMilliseconds, (batch) => { this.currentBatch = batch; }); this.currentBatch.activate(); } /** * Schedules processing of the queue with a delay. * This allows multiple operations to be batched together. */ scheduleProcessing() { this.currentBatch.workArrived(); } /** * Processes the queue immediately, bypassing any delay. */ processQueueNow() { return __awaiter(this, void 0, void 0, function* () { yield this.currentBatch.runNow(); }); } /** * Disposes of the QueueProcessor. */ dispose() { this.currentBatch.terminate(); } } exports.QueueProcessor = QueueProcessor; //# sourceMappingURL=QueueProcessor.js.map