96 lines
2.7 KiB
TypeScript
96 lines
2.7 KiB
TypeScript
import { AggregateRoot, UniqueID } from '../entities';
|
|
import { IDomainEvent } from './DomainEventInterface';
|
|
|
|
export class DomainEvents {
|
|
private static handlersMap: { [key: string]: any } = {};
|
|
private static markedAggregates: AggregateRoot<any>[] = [];
|
|
|
|
/**
|
|
* @method markAggregateForDispatch
|
|
* @static
|
|
* @desc Called by aggregate root objects that have created domain
|
|
* events to eventually be dispatched when the infrastructure commits
|
|
* the unit of work.
|
|
*/
|
|
|
|
public static markAggregateForDispatch(
|
|
aggregate: AggregateRoot<any>
|
|
): void {
|
|
const aggregateFound = !!this.findMarkedAggregateByID(aggregate.id);
|
|
|
|
if (!aggregateFound) {
|
|
this.markedAggregates.push(aggregate);
|
|
}
|
|
}
|
|
|
|
private static dispatchAggregateEvents(
|
|
aggregate: AggregateRoot<any>
|
|
): void {
|
|
aggregate.domainEvents.forEach((event: IDomainEvent) =>
|
|
this.dispatch(event)
|
|
);
|
|
}
|
|
|
|
private static removeAggregateFromMarkedDispatchList(
|
|
aggregate: AggregateRoot<any>
|
|
): void {
|
|
const index = this.markedAggregates.findIndex((a) =>
|
|
a.equals(aggregate)
|
|
);
|
|
this.markedAggregates.splice(index, 1);
|
|
}
|
|
|
|
private static findMarkedAggregateByID(
|
|
id: UniqueID
|
|
): AggregateRoot<any> | undefined {
|
|
let found: AggregateRoot<any> | undefined = undefined;
|
|
|
|
for (const aggregate of this.markedAggregates) {
|
|
if (aggregate.id.equals(id)) {
|
|
found = aggregate;
|
|
}
|
|
}
|
|
|
|
return found;
|
|
}
|
|
|
|
public static dispatchEventsForAggregate(id: UniqueID): void {
|
|
const aggregate = this.findMarkedAggregateByID(id);
|
|
|
|
if (aggregate) {
|
|
this.dispatchAggregateEvents(aggregate);
|
|
aggregate.clearEvents();
|
|
this.removeAggregateFromMarkedDispatchList(aggregate);
|
|
}
|
|
}
|
|
|
|
public static register(
|
|
callback: (event: IDomainEvent) => void,
|
|
eventClassName: string
|
|
): void {
|
|
if (!this.handlersMap.hasOwnProperty(eventClassName)) {
|
|
this.handlersMap[eventClassName] = [];
|
|
}
|
|
this.handlersMap[eventClassName].push(callback);
|
|
}
|
|
|
|
public static clearHandlers(): void {
|
|
this.handlersMap = {};
|
|
}
|
|
|
|
public static clearMarkedAggregates(): void {
|
|
this.markedAggregates = [];
|
|
}
|
|
|
|
private static dispatch(event: IDomainEvent): void {
|
|
const eventClassName: string = event.constructor.name;
|
|
|
|
if (this.handlersMap.hasOwnProperty(eventClassName)) {
|
|
const handlers: any[] = this.handlersMap[eventClassName];
|
|
for (const handler of handlers) {
|
|
handler(event);
|
|
}
|
|
}
|
|
}
|
|
}
|