UNPKG

maxun-core

Version:

Core package for Maxun, responsible for data extraction

82 lines (81 loc) 2.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Concurrency class for running concurrent tasks while managing a limited amount of resources. */ class Concurrency { /** * Constructs a new instance of concurrency manager. * @param {number} maxConcurrency Maximum number of workers running in parallel. */ constructor(maxConcurrency) { /** * Maximum number of workers running in parallel. If set to `null`, there is no limit. */ this.maxConcurrency = 1; /** * Number of currently active workers. */ this.activeWorkers = 0; /** * Queue of jobs waiting to be completed. */ this.jobQueue = []; /** * "Resolve" callbacks of the waitForCompletion() promises. */ this.waiting = []; this.maxConcurrency = maxConcurrency; } /** * Takes a waiting job out of the queue and runs it. */ runNextJob() { const job = this.jobQueue.pop(); if (job) { // console.debug("Running a job..."); job().then(() => { // console.debug("Job finished, running the next waiting job..."); this.runNextJob(); }); } else { // console.debug("No waiting job found!"); this.activeWorkers -= 1; if (this.activeWorkers === 0) { // console.debug("This concurrency manager is idle!"); this.waiting.forEach((x) => x()); } } } /** * Pass a job (a time-demanding async function) to the concurrency manager. \ * The time of the job's execution depends on the concurrency manager itself * (given a generous enough `maxConcurrency` value, it might be immediate, * but this is not guaranteed). * @param worker Async function to be executed (job to be processed). */ addJob(job) { // console.debug("Adding a worker!"); this.jobQueue.push(job); if (!this.maxConcurrency || this.activeWorkers < this.maxConcurrency) { this.runNextJob(); this.activeWorkers += 1; } else { // console.debug("No capacity to run a worker now, waiting!"); } } /** * Waits until there is no running nor waiting job. \ * If the concurrency manager is idle at the time of calling this function, * it waits until at least one job is completed (can be "presubscribed"). * @returns Promise, resolved after there is no running/waiting worker. */ waitForCompletion() { return new Promise((res) => { this.waiting.push(res); }); } } exports.default = Concurrency;