Buses
DomusJS includes three core buses to implement CQRS and event-driven architectures:
✅ Command Bus → Handles actions that change state.
✅ Query Bus → Handles data retrieval requests.
✅ Event Bus → Publishes and distributes domain events.
These buses provide clean separation between application concerns and make it easy to extend or swap implementations.
Command Bus
Section titled “Command Bus”What It Does
Section titled “What It Does”- Dispatches commands to their corresponding handlers.
- Used for operations that change system state.
Default Implementation
Section titled “Default Implementation”The infrastructure module ships with InMemoryCommandBus
, which uses tsyringe
to resolve handlers.
const commandBus = container.resolve<CommandBus>('CommandBus');await commandBus.dispatch(new CreateUserCommand(...));
Custom Implementations
Section titled “Custom Implementations”You can swap in your own implementation (e.g., using RabbitMQ):
container.register<CommandBus>('CommandBus', { useClass: RabbitMQCommandBus });
✅ As long as it follows the CommandBus
interface, it integrates smoothly.
Query Bus
Section titled “Query Bus”What It Does
Section titled “What It Does”- Handles read-only operations.
- Returns data without modifying system state.
Default Implementation
Section titled “Default Implementation”The InMemoryQueryBus
is provided by default:
const queryBus = container.resolve<QueryBus>('QueryBus');const user = await queryBus.ask(new GetUserByIdQuery(userId));
Custom Implementations
Section titled “Custom Implementations”You can create wrappers (e.g., for caching, logging) or distributed setups:
container.register<QueryBus>('QueryBus', { useClass: DistributedQueryBus });
✅ This makes reads scalable and modular.
Event Bus
Section titled “Event Bus”What It Does
Section titled “What It Does”- Publishes domain events to subscribed handlers.
- Enables decoupled, reactive architectures.
Default Implementation
Section titled “Default Implementation”The InMemoryEventBus
works out of the box for synchronous, in-process eventing.
const eventBus = container.resolve<EventBus>('EventBus');await eventBus.publish([new UserRegisteredEvent(...) ]);
Provided Distributed Implementations
Section titled “Provided Distributed Implementations”DomusJS already includes ready-to-use implementations for distributed eventing:
✅ RabbitMQ → RabbitMQEventBus
✅ Google Pub/Sub → GooglePubSubEventBus
To use them, simply register them inside your registerDomusCore()
call:
registerDomusCore({ eventBus: new RabbitMQEventBus(), // or GooglePubSubEventBus});
✅ This enables cross-service event propagation for microservice architectures.
Best Practices
Section titled “Best Practices”✅ Register all buses via registerDomusCore()
or by overriding afterwards.
✅ Keep command, query, and event flows separate for clarity.
✅ Use middleware patterns (logging, metrics, tracing) around bus executions.
✅ For microservices, use distributed buses to communicate across services.