Lead Maintainer: Vitaly Aminev
Easily design, develop & distribute your code with opinionated microservices toolkit. It's designed to provide highly extensible, defined structure so that you only have to worry about implementing business logic and nothing else. Make sure that every minute you spend counts.
yarn add @microfleet/core
or npm i @microfleet/core
First of all it's a middle ground between usability and flexibility, ease of use and scalability. Unless you are Facebook or Google it's very likely that you can handle hundreds of thousands of TPS on a bunch of small and slow VMs with @microfleet. It's not a walk in the park, but after grasping basic concepts of this - you'd be able to create robust microservices within minutes.
A lot of components could still be improved and a lot of common use-cases handled, we've been working on this since 2015 and we are commited to constantly improving this toolkit as we believe that almost every app out there shares common functionality. We want to make a toolkit that allows you to hack together production grade apps within days to be able to prove your startup concept, roll out safely and actually handle load if your idea is the next Big One.
Having this concept in mind there is already a solid basis for this:
Most of the time it's easy to combine these services in a lego-like fashion providing you with a mix of desired functionality.
So, how do we use it? After many iterations we have what we believe is a great structure for the code, which allows for easy service creation. Here is an example of action:
function addAction({ params }) {
return params[0] + params[1];
}
module.exports = addAction;
How do we test it? Easiest for us is https://github.com/jakubroztocil/httpie, go ahead and install it if you still haven't
It's clear that params could be anything and our little action handler won't do any good in that way as we have no means of enforcing validation of input arguments. Rejoice, this was one of the first things we've done. By default every handler will look for a relevant json-schema
under <project_root>/schemas/<actionName>.json
. Lets create that file now with the following content:
{
"$id": "add",
"type": "array",
"items": {
"minItems": 2,
"maxItems": 2,
"type": "number"
}
}
It will ensure that payload is validated, it must be an array and contain 2 numbers. You get the gist of it. Let's try running request without any payload:
http localhost:3000/mservice/add
HTTP/1.1 400 Bad Request
Connection: keep-alive
Date: Mon, 22 May 2017 21:11:32 GMT
Transfer-Encoding: chunked
cache-control: no-cache
content-encoding: gzip
content-type: application/json; charset=utf-8
vary: accept-encoding
{
"error": "Bad Request",
"message": "add validation failed: data should be array",
"name": "ValidationError",
"statusCode": 400
}
And with the correct payload:
echo '[1,2]' | http POST localhost:3000/mservice/add
HTTP/1.1 200 OK
Connection: keep-alive
Date: Mon, 22 May 2017 21:21:33 GMT
Transfer-Encoding: chunked
cache-control: no-cache
content-encoding: gzip
content-type: application/json; charset=utf-8
vary: accept-encoding
3
Now on top of it you can build pretty much anything - routes will be created automatically, network topology will follow your configuration, input would be validated. Make sure to check real-world examples with or without database usage. We recommend starting with the @microfleet/mailer service as it contains only 2 actions, but clearly shows most of the concepts.
To ensure smooth and fast development, there are many core plugins that build-up on core functionality. At this point they are all bundled with core toolkit, but expect them to be externalized as toolkit matures.
This includes common functionality plugins:
Based on @microfleet/validation allows to easily validate input args based on json-schema.
Create directory schemas
and populate it with schemas, where names correspond to actions.
Adds following API to the microservice instance:
.validator
- instance of ms-validation
.validate<T>(schema: string, input: T) => Promise<Error | T>
- Promise-based API that resolves/rejects based.validateSync<T>(schema: string, input: T) => { error?: Error, doc: T }
- sync API, which always returns an object. If validation failed - it populates error property with an instance of Error. Doc is a modified version of input arg with coercion, defaults, filtering of props and so on.Creates bunyan logger, with streams based on passed configuration and extends microservice instance with the following methods:
.log
- instance of bunyan loggerInitializes router, which scans folders for actions and builds routing tree for for enabled transports.
Router controls request lifecycle, which tries to mimic hapi.js lifecycle as closely as possible, with unified interface for multiple transports.
Currently supports AMQP
(@microfleet/transport-amqp
), HTTP
(hapi.js
) and Socket.IO
.
Default sensible configurations are provided.
Stock configuration looks for all **/*.js
files in src/actions
directory, enables hapi.js
based HTTP handler on port 3000.
On top of it enables 2 router extension, which provide request logging & automatic json-schema matching for actions based on their names.
We've struggled to make sure that requests loop the same regardless of transport selected and the lifecycle was adopted from hapi.js model as it proved to be extremely easy to follow and extend.
Lifecycle goes in the following way:
ServiceAction
for the route
passed from the transport, throws 404 error or maintance mode
error.
(this: Microfleet, request: ServiceRequest) => void
ServiceRequest.error
) from request
partServiceAction.auth
is present.
(this: Microfleet, request: ServiceRequest) => void
auth
property contains credentials to ServiceRequest
ServiceRequest.error
) from auth
partjson-schema
if ServiceAction.schema
is defined
(this: Microfleet, request: ServiceRequest) => void
ServiceRequest.error
) if handlers present(this: Microfleet, request: ServiceRequest) => void
ServiceAction.allowed
ServiceRequest.error
) from allowed
part(this: Microfleet, request: ServiceRequest) => void
handler
(this: Microfleet, request: ServiceRequest) => void
hapi
plugin to be enabledAs with any healthy toolkit - there is always plenty to add. These are some of the major features that we are working towards. Our goal to ensure that most of the apps can be created by writing a simple integration layer with your business logic and a bunch of human-readable configuration
more docs
authentication framework:
transport-agnostic inter-service communication API
Tracing API: visibility into transactions
Development of the @microfleet generously supported by contributions from individuals and corporations. If you are benefiting from @microfleet and would like to help keep the project financially sustainable, please send an email to Vitaly Aminev