Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ryardley/microlithic-example
Example implementation of a microlithic app
https://github.com/ryardley/microlithic-example
Last synced: 21 days ago
JSON representation
Example implementation of a microlithic app
- Host: GitHub
- URL: https://github.com/ryardley/microlithic-example
- Owner: ryardley
- Created: 2018-10-18T16:37:11.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2019-02-13T23:38:16.000Z (over 5 years ago)
- Last Synced: 2024-10-11T04:02:31.895Z (about 1 month ago)
- Language: TypeScript
- Homepage:
- Size: 951 KB
- Stars: 2
- Watchers: 3
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Microlithic Application
This is a little toy architecture I have been playing around with. The goal here is to outline some concepts and test the use of rxmsg in context.
I chose the example of trying to spread authentication over an event bus. This is not something I would normally do in a production system however it has some more complex mechanics than basic CRUD or saving a post let's say.
## Microlithicism
A microlithic application is deployed as a monolith but conceptually functions like a microservice system.
The way we do this is by sending messages between select component boundaries using events.
When ready to scale up we can replace the event busses with ones that proxy scalable services such as Kafka or RabbitMQ.
### Patterns
Conceptually we use two patterns that work well with each other, EventSourcing and CQRS.
Here is a high level overview:
![CQRS](docs/CQRS-03.png)
**EventSourcing** means considering the state of your application as an immutable series of events.
**CQRS** basically means separating your query system from your command system.
The advantages of doing this in a microservices architecture is that you can scale your reads at a different rate to your writes and it ensures that so long as you are happy with eventual consistency your app should be able to take a huge amount of traffic.
### Example of sending synchronous messages
Some might ask well how do you send a synchronous message such as a query for state using a system like this?
Here is an example from our routes file here. In this example we want to get the current user email information. To do this we need to send a `CurrentUserRequest` message across the query event bus. Listening for that message is a service that will send a `CurrentUserResponse` message back.
```typescript
// Create the event
const event = CurrentUserRequest.correlated({
id: 123
})// Dispatch it
QueryBus.dispatch(event);// Wait for the response with a 10 second timeout
const response = await QueryBus.waitForEvent(
event.correlationId,
'CurrentUserResponse',
10000
);console.log(reponse); // {email:"[email protected]"}
```### Sending an Asynchronous Message
Naturally you don't need to wait for a response and can simply shoot off a command and continue processing or provide some kind of optimistic response to the user.```typescript
CommandBus.dispatch(
LogoutCommand({
sid
})
);
```### Multiple Busses
You can also wait for events off different buses:```typescript
const event = LoginCommand.correlated({
email,
password,
sid
})CommandBus.dispatch(event);
await EventBus.waitForEvent(
event.correlationId,
'UserLoggedInEvent'
);
```### Waiting for Multiple Events
You can wait for the first correlated error event from a selection of events:```typescript
const event = LoginCommand.correlated({
email:"[email protected]",
password: "fa352471287",
sid: "12345687651234"
})// Dispatch it
CommandBus.dispatch(event);// This will wait for the first correlated resultant event
const answer = await EventBus.waitForEvent(
event.correlationId,
[
'UserLoggedInEvent',
'LoginErrorRaised'
]
);
```### Listening for messages
Basically to subscribe to events you simply call the subscribe method on the event bus:
```typescript
CommandBus.subscribe('MyCommandEvent', myCommandFunction);
```A full command function example might look like this:
```typescript
async function registerCommand ({
email,
password:hashedPassword,
role,
correlationId
}: RegisterCommand) {// Go save this user and their data
dispatch(
UserRegisteredEvent({
correlationId,
email,
password: hashedPassword,
role
})
);
};CommandBus.subscribe('RegisterCommand', registerCommand);
```