-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
100 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Command bus | ||
|
||
## Intro | ||
|
||
A command bus is a fundamental architectural pattern used in software development, particularly in the context of | ||
building applications following the Command Query Responsibility Segregation (CQRS) paradigm. | ||
|
||
Acting as a mediator between the application's components, the command bus receives commands to perform from | ||
various parts of the system and routes them to the appropriate handlers or command handlers responsible for executing | ||
the requested operations. This abstraction simplifies the communication flow within the application, decoupling the | ||
sender of the command from its execution logic. By centralizing command processing, the command bus promotes a cleaner | ||
and more maintainable codebase, enhancing modularity and scalability in complex software systems. | ||
|
||
## Local Command Bus | ||
|
||
Ddd toolkit provides a simple in-memory implementation of a command bus. | ||
|
||
- `register`: register a command handler for a specific command. | ||
- `send`: executes a command. Resolves immediately, without waiting for the effective execution of the command. | ||
- `sendSync`: executes a command. Resolves when the effective execution of the command is completed. | ||
|
||
::: info | ||
The `send` method implements a retry mechanism by default. This means that if the command handler throws an error, the | ||
command bus will retry to execute the command handler until the maximum number of retries is reached. | ||
::: | ||
|
||
::: warning PRAGMATIC ALERT 📣 | ||
As mentioned above, the greatest benefit of using a command bus over direct method calls is to centralise and | ||
standardise. | ||
We wanted to include the send method (in addition to sendSync) because in some contexts there is a risk of coupling to | ||
synchronous commands. Send allows us to develop our application without assuming that commands are local (and thus can | ||
return data / can be synchronous). | ||
|
||
In general, when asynchronicity is introduced into a system, complexity explodes. | ||
|
||
::: | ||
|
||
## Basic usage | ||
|
||
Define CommandBus | ||
|
||
```typescript | ||
import { LocalCommandBus } from '@fizzbuds/ddd-toolkit'; | ||
|
||
|
||
export class CommandBus extends LocalCommandBus { | ||
constructor() { | ||
super(new Logger(CommandBus.name)); | ||
} | ||
} | ||
``` | ||
|
||
Define a command | ||
|
||
```typescript | ||
type DeleteMemberCommandPayload = { memberId: string }; | ||
|
||
class DeleteMemberCommand extends Command<DeleteMemberCommandPayload> { | ||
constructor(public readonly payload: DeleteMemberCommandPayload) { | ||
super(payload); | ||
} | ||
} | ||
|
||
``` | ||
|
||
Define a command handler | ||
|
||
```typescript | ||
import { LocalCommandBus } from '@fizzbuds/ddd-toolkit'; | ||
|
||
|
||
export class DeleteCommandHandler implements ICommandHandler<DeleteMemberCommand> { | ||
async handle({ payload }: DeleteMemberCommand) { | ||
// Delete member logic | ||
} | ||
} | ||
``` | ||
|
||
Try it out | ||
|
||
```typescript | ||
const commandBus = new CommandBus(); | ||
|
||
commandBus.registerHandler(DeleteMemberCommand, new DeleteCommandHandler()) | ||
|
||
|
||
await commandBus.send(new DeleteMemberCommand({ memberId: '123' })); | ||
|
||
``` | ||
|
||
|
||
|
||
|
||
|
||
|
||
|