@cloud-copilot/iam-lens
Version:
Visibility in IAM in and across AWS accounts
101 lines • 3.42 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PullBasedJobRunner = void 0;
/**
* A Job runner that pulls tasks from a source and executes them concurrently.
*
* This will run a fixed number of workers up to the specified concurrency.
*/
class PullBasedJobRunner {
concurrency;
getNextTask;
makeJobForTask;
onComplete;
isAcceptingWork = true;
activeJobs = 0;
workers = [];
idlePromise = undefined;
/**
* Creates an instance of PullBasedJobRunner.
*
* @param concurrency the number of concurrent workers to run
* @param getNextTask a function that returns the next task for a worker
* @param makeJobForTask a function that creates a job for the given task details
* @param onComplete a function that is called when a job is completed
*/
constructor(concurrency, getNextTask, makeJobForTask, onComplete) {
this.concurrency = concurrency;
this.getNextTask = getNextTask;
this.makeJobForTask = makeJobForTask;
this.onComplete = onComplete;
for (let i = 0; i < this.concurrency; i++) {
this.workers.push(this.worker(i));
}
}
/**
* Create a worker for running tasks from the queue.
*
* @param workerId the ID of the worker
* @returns A promise that resolves when the worker is done processing tasks.
*/
async worker(workerId) {
while (true) {
const task = await this.getNextTask(workerId);
if (!task) {
// If no more tasks are available, and we are not accepting work, exit the loop
if (!this.isAcceptingWork) {
return;
}
await this.waitForWork();
continue;
}
this.activeJobs++;
const job = this.makeJobForTask(task);
const context = { workerId };
try {
const value = await job.execute({ ...context, properties: job.properties });
await this.onComplete({ status: 'fulfilled', value, properties: job.properties });
}
catch (reason) {
await this.onComplete({ status: 'rejected', reason, properties: job.properties });
}
finally {
this.activeJobs--;
}
}
}
/**
* Waits for work to be available in the queue.
*
* @returns A promise that resolves when new jobs are available to work on.
*/
async waitForWork() {
if (this.idlePromise) {
return this.idlePromise.promise;
}
let resolve = () => { };
let promise = new Promise((res) => {
resolve = res;
});
this.idlePromise = { resolve, promise };
return this.idlePromise.promise;
}
/**
* Finish all work and shut down the workers when no further tasks are available.
*/
async finishAllWork() {
this.isAcceptingWork = false;
this.notifyWorkAvailable();
await Promise.all(this.workers);
this.workers = [];
}
/**
* Notify the workers that new work is available.
*/
notifyWorkAvailable() {
this.idlePromise?.resolve();
this.idlePromise = undefined;
}
}
exports.PullBasedJobRunner = PullBasedJobRunner;
//# sourceMappingURL=JobRunner.js.map