signalk-parquet
Version:
Vessel data Parquet file archive with automated value and geospatial triggers. History API compliant with cloud backups and queries.
66 lines • 1.93 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConcurrencyLimiter = void 0;
/**
* Limits the number of concurrent promise executions
*
* @example
* const limiter = new ConcurrencyLimiter(5);
* const results = await limiter.map(items, async (item) => {
* return await processItem(item);
* });
*/
class ConcurrencyLimiter {
constructor(maxConcurrent = 10) {
this.running = 0;
this.queue = [];
if (maxConcurrent <= 0) {
throw new Error('maxConcurrent must be positive');
}
this.maxConcurrent = maxConcurrent;
}
/**
* Execute an async function with concurrency limiting
*/
async execute(fn) {
// Wait if at capacity
while (this.running >= this.maxConcurrent) {
await new Promise(resolve => this.queue.push(resolve));
}
this.running++;
try {
return await fn();
}
finally {
this.running--;
// Resume next queued operation
const next = this.queue.shift();
if (next) {
next();
}
}
}
/**
* Map over an array with concurrency limiting
* Similar to Promise.all() but with controlled concurrency
*
* @param items - Array of items to process
* @param fn - Async function to execute for each item
* @returns Array of results in the same order as input
*/
async map(items, fn) {
return Promise.all(items.map((item, index) => this.execute(() => fn(item, index))));
}
/**
* Get current concurrency statistics
*/
getStats() {
return {
running: this.running,
queued: this.queue.length,
maxConcurrent: this.maxConcurrent,
};
}
}
exports.ConcurrencyLimiter = ConcurrencyLimiter;
//# sourceMappingURL=concurrency-limiter.js.map