Skip to content

Commit a4605d2

Browse files
authored
Merge pull request #65 from CodelyTV/part_four_command_bus
Part four command bus
2 parents 762b037 + 3ad53bc commit a4605d2

File tree

20 files changed

+178
-112
lines changed

20 files changed

+178
-112
lines changed

src/Contexts/Mooc/Courses/application/CourseCreator.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,12 @@ import { CourseName } from '../domain/CourseName';
66
import { CourseDuration } from '../domain/CourseDuration';
77
import { EventBus } from '../../../Shared/domain/EventBus';
88

9+
type Params = {
10+
courseId: CourseId;
11+
courseName: CourseName;
12+
courseDuration: CourseDuration;
13+
};
14+
915
export class CourseCreator {
1016
private repository: CourseRepository;
1117
private eventBus: EventBus;
@@ -15,11 +21,11 @@ export class CourseCreator {
1521
this.eventBus = eventBus;
1622
}
1723

18-
async run(request: CreateCourseRequest): Promise<void> {
24+
async run({ courseId, courseName, courseDuration }: Params): Promise<void> {
1925
const course = Course.create(
20-
new CourseId(request.id),
21-
new CourseName(request.name),
22-
new CourseDuration(request.duration)
26+
courseId,
27+
courseName,
28+
courseDuration
2329
);
2430

2531
await this.repository.save(course);
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Command } from '../../../Shared/domain/Command';
2+
3+
type Params = {
4+
id: string;
5+
name: string;
6+
duration: string;
7+
};
8+
9+
export class CreateCourseCommand extends Command {
10+
id: string;
11+
name: string;
12+
duration: string;
13+
14+
constructor({ id, name, duration }: Params) {
15+
super();
16+
this.id = id;
17+
this.name = name;
18+
this.duration = duration;
19+
}
20+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { CreateCourseCommand } from './CreateCourseCommand';
2+
import { CommandHandler } from '../../../Shared/domain/CommandHandler';
3+
import { CourseCreator } from './CourseCreator';
4+
import { Command } from '../../../Shared/domain/Command';
5+
import { CourseId } from '../../Shared/domain/Courses/CourseId';
6+
import { CourseName } from '../domain/CourseName';
7+
import { CourseDuration } from '../domain/CourseDuration';
8+
9+
export class CreateCourseCommandHandler implements CommandHandler<CreateCourseCommand> {
10+
constructor(private courseCreator: CourseCreator) {}
11+
12+
subscribedTo(): Command {
13+
return CreateCourseCommand;
14+
}
15+
16+
async handle(command: CreateCourseCommand): Promise<void> {
17+
const courseId = new CourseId(command.id);
18+
const courseName = new CourseName(command.name);
19+
const courseDuration = new CourseDuration(command.duration);
20+
await this.courseCreator.run({ courseId, courseName, courseDuration });
21+
}
22+
}
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
export abstract class Command {
2-
static COMMAND_NAME: string;
3-
}
1+
export abstract class Command {}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Command } from './Command';
22

33
export interface CommandBus {
4-
dispatch(command: Command): void;
4+
dispatch(command: Command): Promise<void>;
55
}
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import { Command } from "./Command";
1+
import { Command } from './Command';
22

33
export interface CommandHandler<T extends Command> {
4-
subscribedTo(): T;
5-
6-
handle(command: T): void;
7-
}
4+
subscribedTo(): Command;
5+
handle(command: T): Promise<void>;
6+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Command } from './Command';
2+
3+
export class CommandNotRegisteredError extends Error {
4+
constructor(command: Command) {
5+
super(`The command <${command.constructor.name}> hasn't a command handler associated`);
6+
}
7+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Command } from '../../domain/Command';
2+
import { CommandHandler } from '../../domain/CommandHandler';
3+
import { CommandNotRegisteredError } from '../../domain/CommandNotRegisteredError';
4+
5+
export class CommandHandlersInformation {
6+
private commandHandlersMap: Map<Command, CommandHandler<Command>>;
7+
8+
constructor(commandHandlers: Array<CommandHandler<Command>>) {
9+
this.commandHandlersMap = this.formatHandlers(commandHandlers);
10+
}
11+
12+
private formatHandlers(commandHandlers: Array<CommandHandler<Command>>): Map<Command, CommandHandler<Command>> {
13+
const handlersMap = new Map();
14+
15+
commandHandlers.forEach(commandHandler => {
16+
handlersMap.set(commandHandler.subscribedTo(), commandHandler);
17+
});
18+
19+
return handlersMap;
20+
}
21+
22+
public search(command: Command): CommandHandler<Command> {
23+
const commandHandler = this.commandHandlersMap.get(command.constructor);
24+
25+
if (!commandHandler) {
26+
throw new CommandNotRegisteredError(command);
27+
}
28+
29+
return commandHandler;
30+
}
31+
}
Lines changed: 6 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,13 @@
1-
import { CommandBus } from './../../domain/CommandBus';
21
import { Command } from '../../domain/Command';
3-
import { NoHandlerForMessageError } from './NoHandlerForMessageError';
4-
import { CommandHandler } from '../../domain/CommandHandler';
5-
6-
export class CommandHandlersInformation {
7-
private commandHandlersMap: Map<string, CommandHandler<Command>>;
8-
9-
constructor(commandHandlers: Array<CommandHandler<Command>>) {
10-
this.commandHandlersMap = this.formatHandlers(commandHandlers);
11-
}
12-
13-
private formatHandlers(commandHandlers: Array<CommandHandler<Command>>) {
14-
const handlersMap = new Map();
15-
16-
commandHandlers.forEach(commandHandler => {
17-
handlersMap.set(commandHandler.subscribedTo(), commandHandler);
18-
});
19-
20-
return handlersMap;
21-
}
22-
23-
public getHandler(command: Command) {
24-
return this.commandHandlersMap.get(command.constructor.name);
25-
}
26-
}
2+
import { CommandBus } from './../../domain/CommandBus';
3+
import { CommandHandlersInformation } from './CommandHandlersInformation';
274

285
export class InMemoryCommandBus implements CommandBus {
29-
constructor(private commandHandlersInformation: CommandHandlersInformation) {
30-
}
31-
32-
dispatch(command: Command): void {
33-
const handler = this.commandHandlersInformation.getHandler(command);
6+
constructor(private commandHandlersInformation: CommandHandlersInformation) {}
347

35-
if (!handler) {
36-
throw new NoHandlerForMessageError(command);
37-
}
8+
async dispatch(command: Command): Promise<void> {
9+
const handler = this.commandHandlersInformation.search(command);
3810

39-
handler.handle(command);
11+
await handler.handle(command);
4012
}
4113
}

src/Contexts/Shared/infrastructure/CommandBus/NoHandlerForMessageError.ts

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)