acelga-bus
Version:
An extensible typescript message bus with support for middlewares
95 lines (74 loc) • 2.65 kB
text/typescript
import {Dispatcher} from './single';
import {
Constructable,
EventSubscriptionCallback,
IScheduler,
ErrorLogger,
PipelinePlan,
PipelineResult,
ExecutionResult,
PipelineExecutionResult,
PipelineFactory,
} from '../interfaces';
export default class BulkDispatcher<T> {
dispatcher: Dispatcher<T>;
scheduler: IScheduler<T>;
pipelineFactory: PipelineFactory<T>;
errorLogger: ErrorLogger;
constructor(dispatcher: Dispatcher<T>, scheduler: IScheduler<T>, pipelineFactory: PipelineFactory<T>, errorLogger: ErrorLogger) {
this.dispatcher = dispatcher;
this.scheduler = scheduler;
this.pipelineFactory = pipelineFactory;
this.errorLogger = errorLogger;
}
public on<T1 extends T>(eventType: Constructable<T1>, callback: EventSubscriptionCallback<T1> ): void {
return this.dispatcher.on(eventType, callback);
}
public onAny(callback: EventSubscriptionCallback<T>): void {
return this.dispatcher.onAny(callback);
}
public async trigger<R extends T = T>(events: R[]): Promise<ExecutionResult<T, R>[]> {
try {
const plan = this.scheduler.schedule(events);
const pipelinesPromises = plan.plan.map(pipelinePlan => this.executePipelinePlan(pipelinePlan));
const results: any[] = await this.mapPipelinePromises(pipelinesPromises);
const errors = this.getAllErrors<R>(results);
if (errors.length){
return Promise.resolve(errors);
}
return [];
} catch (error) {
this.errorLogger(error);
return Promise.reject(error);
}
}
protected getAllErrors<R extends T = T>(results: Array<PipelineResult<T, R>>): ExecutionResult<T, R>[] {
const errors: PipelineResult<T, R> = [];
results.forEach(result => {
result.forEach(error => errors.push(error));
});
return errors;
}
public isListened(eventType: Constructable<T>): boolean {
return this.dispatcher.isListened(eventType);
}
protected executePipelinePlan(pipelinePlan: PipelinePlan<T>) {
const pipeline = this.pipelineFactory(this.dispatcher);
if (pipelinePlan.preserveOrder)
return pipeline.executeStopOnError(pipelinePlan.payloads);
return pipeline.executeContinueOnError(pipelinePlan.payloads);
}
protected async mapPipelinePromises(pipelines: PipelineExecutionResult<T>[]){
const results: any[] = [];
const pipelinesPromises = pipelines.map((pipeline, index) => {
return pipeline
.then(result => results[index] = result)
.catch((error: any) => this.errorLogger(error));
});
await Promise.all(pipelinesPromises);
return results;
}
public off<T1 extends T>(eventType: Constructable<T1>, callback?: EventSubscriptionCallback<T1> ): void {
this.dispatcher.off(eventType, callback);
}
}