UNPKG

@ribajs/shopify

Version:

Shopify extension for Riba.js

203 lines 15.2 kB
import { PriorityQueue } from "./priority-queue.service.js"; export class PQueue { queue = new PriorityQueue(); _carryoverConcurrencyCount; _isIntervalIgnored; _intervalCount = 0; _intervalCap; _interval; _intervalId; _intervalEnd = 0; _timeoutId; _pendingCount = 0; _concurrency; _isPaused; _resolveEmpty; _resolveIdle; constructor(options) { options = Object.assign({ carryoverConcurrencyCount: false, intervalCap: Infinity, interval: 0, concurrency: Infinity, autoStart: true, queueClass: PriorityQueue, }, options); if (!(typeof options.concurrency === "number" && options.concurrency >= 1)) { throw new TypeError(`Expected \`concurrency\` to be a number from 1 and up, got \`${options.concurrency}\` (${typeof options.concurrency})`); } if (!(typeof options.intervalCap === "number" && options.intervalCap >= 1)) { throw new TypeError(`Expected \`intervalCap\` to be a number from 1 and up, got \`${options.intervalCap}\` (${typeof options.intervalCap})`); } if (!(typeof options.interval === "number" && Number.isFinite(options.interval) && options.interval >= 0)) { throw new TypeError(`Expected \`interval\` to be a finite number >= 0, got \`${options.interval}\` (${typeof options.interval})`); } this._carryoverConcurrencyCount = options.carryoverConcurrencyCount; this._isIntervalIgnored = options.intervalCap === Infinity || options.interval === 0; this._intervalCount = 0; this._intervalCap = options.intervalCap; this._interval = options.interval; this._intervalId = undefined; this._intervalEnd = 0; this._timeoutId = null; this.queue = new options.queueClass(); this._pendingCount = 0; this._concurrency = options.concurrency; this._isPaused = options.autoStart === false; this._resolveEmpty = () => { }; this._resolveIdle = () => { }; } add(fn, options) { return new Promise((resolve, reject) => { const run = () => { this._pendingCount++; this._intervalCount++; try { Promise.resolve(fn()).then((val) => { resolve(val); this._next(); }, (err) => { reject(err); this._next(); }); } catch (err) { reject(err); this._next(); } }; this.queue.enqueue(run, options); this._tryToStartAnother(); }); } addAll(fns, options) { return Promise.all(fns.map((fn) => this.add(fn, options))); } start() { if (!this._isPaused) { return; } this._isPaused = false; while (this._tryToStartAnother()) { } } pause() { this._isPaused = true; } clear() { this.queue = new PriorityQueue(); } onEmpty() { if (this.queue.size === 0) { return Promise.resolve(); } return new Promise((resolve) => { const existingResolve = this._resolveEmpty; this._resolveEmpty = () => { existingResolve(); resolve(); }; }); } onIdle() { if (this._pendingCount === 0 && this.queue.size === 0) { return Promise.resolve(); } return new Promise((resolve) => { const existingResolve = this._resolveIdle; this._resolveIdle = () => { existingResolve(); resolve(); }; }); } get _doesIntervalAllowAnother() { return this._isIntervalIgnored || this._intervalCount < this._intervalCap; } get _doesConcurrentAllowAnother() { return this._pendingCount < this._concurrency; } _next() { this._pendingCount--; this._tryToStartAnother(); } _resolvePromises() { this._resolveEmpty(); this._resolveEmpty = () => { }; if (this._pendingCount === 0) { this._resolveIdle(); this._resolveIdle = () => { }; } } _onResumeInterval() { this._onInterval(); this._initializeIntervalIfNeeded(); this._timeoutId = null; } _intervalPaused() { const now = Date.now(); if (typeof this._intervalId === undefined) { const delay = this._intervalEnd - now; if (delay < 0) { this._intervalCount = this._carryoverConcurrencyCount ? this._pendingCount : 0; } else { if (this._timeoutId === null) { this._timeoutId = setTimeout(() => this._onResumeInterval(), delay); } return true; } } return false; } _tryToStartAnother() { if (this.queue.size === 0) { clearInterval(this._intervalId); this._intervalId = undefined; this._resolvePromises(); return false; } if (!this._isPaused) { const canInitializeInterval = !this._intervalPaused(); if (this._doesIntervalAllowAnother && this._doesConcurrentAllowAnother) { this.queue.dequeue()(); if (canInitializeInterval) { this._initializeIntervalIfNeeded(); } return true; } } return false; } _initializeIntervalIfNeeded() { if (this._isIntervalIgnored || this._intervalId !== null) { return; } this._intervalId = setInterval(() => this._onInterval(), this._interval); this._intervalEnd = Date.now() + this._interval; } _onInterval() { if (this._intervalCount === 0 && this._pendingCount === 0) { clearInterval(this._intervalId); this._intervalId = undefined; } this._intervalCount = this._carryoverConcurrencyCount ? this._pendingCount : 0; while (this._tryToStartAnother()) { } } get size() { return this.queue.size; } get pending() { return this._pendingCount; } get isPaused() { return this._isPaused; } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicC1xdWV1ZS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcnZpY2VzL3AtcXVldWUuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFNUQsTUFBTSxPQUFPLE1BQU07SUFDVixLQUFLLEdBQUcsSUFBSSxhQUFhLEVBQUUsQ0FBQztJQUUzQiwwQkFBMEIsQ0FBUztJQUNuQyxrQkFBa0IsQ0FBVTtJQUM1QixjQUFjLEdBQUcsQ0FBQyxDQUFDO0lBQ25CLFlBQVksQ0FBa0I7SUFDOUIsU0FBUyxDQUFTO0lBQ2xCLFdBQVcsQ0FBTztJQUNsQixZQUFZLEdBQUcsQ0FBQyxDQUFDO0lBQ2pCLFVBQVUsQ0FBYTtJQUV2QixhQUFhLEdBQUcsQ0FBQyxDQUFDO0lBQ2xCLFlBQVksQ0FBa0I7SUFDOUIsU0FBUyxDQUFVO0lBRW5CLGFBQWEsQ0FBWTtJQUN6QixZQUFZLENBQVk7SUFFaEMsWUFBWSxPQUFZO1FBQ3RCLE9BQU8sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUNyQjtZQUNFLHlCQUF5QixFQUFFLEtBQUs7WUFDaEMsV0FBVyxFQUFFLFFBQVE7WUFDckIsUUFBUSxFQUFFLENBQUM7WUFDWCxXQUFXLEVBQUUsUUFBUTtZQUNyQixTQUFTLEVBQUUsSUFBSTtZQUNmLFVBQVUsRUFBRSxhQUFhO1NBQzFCLEVBQ0QsT0FBTyxDQUNSLENBQUM7UUFFRixJQUNFLENBQUMsQ0FBQyxPQUFPLE9BQU8sQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLE9BQU8sQ0FBQyxXQUFXLElBQUksQ0FBQyxDQUFDLEVBQ3RFLENBQUM7WUFDRCxNQUFNLElBQUksU0FBUyxDQUNqQixnRUFDRSxPQUFPLENBQUMsV0FDVixPQUFPLE9BQU8sT0FBTyxDQUFDLFdBQVcsR0FBRyxDQUNyQyxDQUFDO1FBQ0osQ0FBQztRQUVELElBQ0UsQ0FBQyxDQUFDLE9BQU8sT0FB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