UNPKG

hamok

Version:

Lightweight Distributed Object Storage on RAFT consensus algorithm

66 lines (46 loc) 1.43 kB
import { createLogger } from './logger'; type OngoingProcess = () => Promise<unknown>; const logger = createLogger('ConcurrentExecutor'); export class ConcurrentExecutor { private _parked: OngoingProcess[] = []; private _tasks: OngoingProcess[] = []; private _semaphore: number; public constructor( public readonly maxConcurrencyLevel: number ) { if (maxConcurrencyLevel < 1) throw new Error('maxConcurrencyLevel must be greater than 0'); this._semaphore = maxConcurrencyLevel; this.postProcess = this.postProcess.bind(this); } public execute<T = unknown>(action: () => Promise<T>, park = false): Promise<T> { return new Promise<T>((resolve, reject) => { const task = () => action().then(resolve) .catch(reject); if (park) this._parked.push(task); else this._tasks.push(task); this._run(); }); } public flushParkedActions() { this._tasks.push(...this._parked); this._parked = []; this._run(); } private postProcess() { ++this._semaphore; if (this._semaphore > this.maxConcurrencyLevel) { logger.warn('Semaphore is greater than maxConcurrencyLevel'); this._semaphore = this.maxConcurrencyLevel; } this._run(); } private _run() { if (this._tasks.length === 0 || this._semaphore === 0) return; const task = this._tasks.shift(); if (!task) return; --this._semaphore; task() .then(() => this.postProcess()) .catch(this.postProcess); } }