node-cqrs-framework
node-cqrs-framework is a node.js framework that helps you to implement microservices and scalability for cqrs architectures over rabbitmq service discovery.
Advantages
- Think better! Think KISS!
- Configuration-driven oriented framework.
- Only one monolithic project in your github.
- Only one monolithic project to maintain.
- Start only the services you want with configuration file.
- Agnostics commands and queries, they just had to be promises.
- Tests are dissociate from the notion of CQRS.
- Deploy and scale your microservices like you want.
- Automatic services discovery! Thanks rabbitmq.
Installation
$ npm i -S node-cqrs-framework
Description
Beware, you need a rabbitmq running in localhost for all those examples.
Server
The server is the main program, he needs to be start at first. Because the project is configuration-driven, you only need those lines of code to start all selected microservices in a row.
Glob patterns
This syntax will load all pomises in this dirpath and attach a 1:1 queue for execute the promise. And attach two 1:N queues (on for success event, and the second for error event).
server
Simple server
const path = const Server = Serverconst server = // all options from servicebus (see npm)const options = host: 'localhost' port: 5672 user: 'guest' pass: 'guest' timeout: 2000 heartbeat: 10 server startoptions server server
Service
A service is the base element of the CQRS, it's like a microservice or a task. The application result of a service will automaticaly:
- Send an event on the bus in case of success
- Send an event on the bus in case of error
You will never have to use this class, Command and Query extend it.
Command
- "A result" is either a successful application of the command, or an exception.
- Because it extends Service, success event or error event will be automaticaly send on the bus.
How to create a Command ?
Step 1
You need to create a file who contains "Command" in his name.
path/you/want/BasicNopeCommand.js
Step 2
You need to module.exports a promise.
const Promise = const handler = { return { }} moduleexports = handler
Query
From the framework point of view a query is the same as a command, but because of queries roles in the CQRS architecture, this time data will be return.
- "A result" is either data, or an exception
- Because it extends Service, success event or error event will be automaticaly send on the bus
How to create a Query ?
Step 1
You need to create a file who contains "Query" in his name.
path/you/want/BasicNopeQuery.js
Step 2
You need to module.exports a promise.
const Promise = const handler = { return { }} moduleexports = handler
Now it's time to start the server
Classic start:
$ node examples/server.js
But, you can run the server in debug mode.
$ DEBUG=cqrs:* node examples/server.js
Client
It's time to learn how to link all those services and events together, let's me introduce the Client object.
Definitions
A client could be wherever you need it to be, even on another server, or behind a hapiJS/Express server, or why not in another CQRS Server.
You will have three patterns to use the server events bus.
Sender/Receiver pattern
The Send / Receive object pair uses a direct exchange inside of RabbitMQ
Publisher/Subscriber pattern
The Publish / Subscribe object pair uses a fanout exchange inside of RabbitMQ, allowing you to have as many subscribers as you need. Think of pub/sub as an event that gets broadcast to anyone that cares, or no one at all if no one is listening.
Request/Response pattern
The request/response pair uses a "topic" exchange. With a request/response setup, you can send a request for information and respond to it.
Send a Query
- When the server start and load your handlers, receivers are created in the server.
- Sender client is a classic fire and forget on the bus. In return you will have only a result who informs you if the command or the query has been executed succesfully or not.
Create a file client-sender.js, and and this code in:
const Client = Clientconst client = // all options from servicebus (see npm)const options = host: 'localhost' port: 5672 user: 'guest' pass: 'guest' timeout: 2000 heartbeat: 10 client startoptions client client
Nota
- The pattern BasicNopeQuery.* will receive Error and Success event for one specific Query.
- The pattern *.Error will receive Errors for all Commands and Queries.
Now it's time to start the client-send
Classic start:
$ node examples/client-sender.js
But, you can run the client in debug mode.
$ DEBUG=cqrs:* node examples/client-sender.js
Result will be:
type: 'Query' name: 'BasicNopeQuery' event: 'BasicNopeQuery.Success' params: message: 'This is a query' exectime: 1004 result: data: true
Request a Query
- When the client start a specific queue is created on the server.
- The server will have in the data received an automatic header to help him answering the client who called.
- Events succes or error are also published.
Create a file client-request.js, and and this code in:
const Client = Clientconst client = client start client client
Result from the success event will be:
success type: 'Query' name: 'BasicNopeQuery' event: 'BasicNopeQuery.Success' params: message: 'This is a query' __headers: 'x-client-id': 'Client.Response.38057d6b-bd49-4b4b-9727-35146c43789a' 'x-request-id': 'cb0d0e12-8f8c-4267-a20f-fb05c653aba6' exectime: 1001 result: data: true
Result from the response callback will be:
result type: 'Query' name: 'BasicNopeQuery' event: 'BasicNopeQuery.Success' params: message: 'This is a query' exectime: 1001 result: data: true