jinaga
Version:
Data management for web and mobile applications.
138 lines • 4.41 kB
JavaScript
"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