import {EventEmitter} from 'events' import {LinkedList} from './LinkedList' import {Deferred} from './Deferred' import { Worker } from './Worker' import { ExecutorFactory } from './Executor' import { IRequest } from './ITask' interface ITaskEventHandler { success: () => void failure: (err: Error) => void } export interface ITaskManager { post(task: T): void wait(): Promise } export class TaskManager implements ITaskManager { protected taskQueue = new LinkedList>() protected workers: Set> = new Set() protected deferredTasks = new Map>() protected taskCount = 0 constructor( readonly n: number = 1, readonly createExecutor: ExecutorFactory, ) { } async post(params: T) { const id = this.getNextTaskId() this.taskQueue.push({ id, params, }) const deferred = new Deferred() this.deferredTasks.set(id, deferred) if (this.workers.size < this.n) { // deliberately do not use promise here const worker = this.startWorker() } return deferred.promise } protected getNextTaskId() { this.taskCount += 1 return this.taskCount } protected async startWorker() { const promise = new Worker( this.createExecutor(), this.taskQueue, response => { const deferred = this.deferredTasks.get(response.id) if (!deferred) { throw new Error('No deferred found for task id:' + response.id) return } if (response.type === 'error') { deferred.reject(response.error) } else { deferred.resolve(response.result) } }, ) .start() this.workers.add(promise) await promise this.workers.delete(promise) } async wait() { const workers = Array.from(this.workers) for (const worker of workers) { await worker } } }