mservice v8.0.0
Microservice core
This module provides boilerplate for microservice core and a few plugins for starters. It sets up convenient connect and close methods,
logging features, as well as input validation. At the same time it is an event emitter and may send log and other events silently.
Migration from 2.x to 3.x
Version 3 bring a neat feature of supporting multiple transports and request lifecycle. Please consult releases page on how to migrate your code
Usage
Extend Mservice class, populate plugins with array of their names. Currently supported:
amqpcassandraelasticsearchhttploggerredisClusterredisSentinelroutersocketIOvalidator
Events:
ready- when all plugins are upclose- when all plugins were disconnectedplugin:connect:pluginName,instanceplugin:close:pluginNameerror,err- on critical error
Example
const path = require('path');
const Mservice = require('mservice');
const ld = require('lodash');
class UserService extends Mservice {
/**
* default options
* @type {Object}
*/
static defaultOpts = {
plugins: ['validator', 'logger', 'amqp', 'redisCluster'],
redis: {
hosts: [{
host: 'localhost',
port: 6379
}],
options: {
keyPrefix: 'nice'
}
},
amqp: {
transport: {
queue: 'roundrobin',
},
},
logger: {
defaultLogger: true,
},
// relative paths will be resolved relatively to the first dir of the file
// on the call stack that is not src/plugins/validator.js or src/index.js
// keep that in mind when creating instances of services
//
// if that's tricky - pass absolute paths!
validator: [ '../schemas' ],
}
constructor(opts = {}) {
super(ld.merge({}, UserService.defaultOpts, opts));
}
}
const userService = new UserService();
// methods that userService will have are explain belowMethods
initPlugin(mod, conf)
Initializes plugin, which has 2 methods: .attach - it would be called with service as context and conf as first arg
When conf is omitted - it looks for mod.name - make sure this is also exported.
.attach can return connect and close functions, which must return promises for starting and stopping the plugin
hook(event, ...args)
Performs Promise.map listeners defined for event. All of them are called with the context of the mservice
and args are applied as a spread. This is useful when you want to track custom event hooks completion in the app.
Constructor accepts hooks Object, which contains of a map of event to a function or array of functions.
They could either be sync or a promise.
Plugins
Validator plugin
When using this plugin - make sure you npm i ms-validation -S
Attaches ms-validation instance to your class on ._validator.
Exposes .validate and .validateSync methods on the class itself.
Pass array of absolute and relative paths when creating service to automatically include your schemas.
They will be available under basename of the file. If names collide - last schemas will overwrite existing ones
// MixedData - any variable to be checked
userService.validate('schemaName', MixedData)
.then(mixedData => {
// passed validation
})
.catch(err => {
// validation failed
})
const validationResult = userService.validateSync('schemaName');
if (validationResult.error) {
// validation failed
// handle error
}
// resulting doc if filter: true was set, otherwise original doc
validationResult.docLogger plugin
When using this plugin - make sure you npm i bunyan -S
Attaches .log method, which is an instance of a bunyan logger.
Provides sane defaults when NODE_ENV is set to development.
If not includes ringBuffer trace logger with 100 records.
Can accept either a boolean value or an existing custom bunyan instance;
logger config
defaultLogger- when options is set totrue- will output to stdout, when tofalse- only to ringBuffer.debug- when debug is on - default log level isdebug, otherwise -info.name- logger name, will have name ofservice._config.nameormserviceif not set.streams- steams config, keys are name of stream, values are stream config
Predefined steams
sentry
logger: {
streams: {
stream: {
dns: 'sentry-dns',
level: 'error',
options: {
// sentry options
},
},
},
}Example
const userService = new UserService({
logger: {
debug: false,
defaultLogger: true
}
});
// will output data to stdout
userService.log.info('Flying just fine!');
// will only save to ringBuffer stream
userService.log.debug('You won\'t see me!');AMQP plugin
When using this plugin, make sure you also do npm i ms-amqp-transport -S
Enables AMQP transport makeomatic/ms-amqp-transport
It allows the service to communicate over AMQP protocol. If service.router
plugin is enabled, then we will make the best attempt to setup listeners
and route incoming messages through this plugin. Attaches ._amqp to service.
Events are emitted when plugin has completed connecting, or disconnecting. First arg is the transport instance
plugin:connect:amqpplugin:close:amqp
const userService = new UserService({
amqp: {
transport: {
queue: 'my-nice-queue',
listen: ['users.ping'],
},
router: {
enabled: true
},
}
});
// messages that are sent to users.ping will be processedRedisCluster plugin
NOTE: you can use only 1 of the plugins for redis - either cluster or sentinel
When using this plugin, make sure you also do npm i ioredis -S
Enables redisCluster communication based on ioredis module.
Allows one to setup connection to redis and communicate with it;
Events are emitted when plugin has completed connecting, or disconnecting. First arg is the transport instance
plugin:connect:redisClusterplugin:close:redisCluster
const userService = new UserService({
plugins: [ 'redisCluster' ],
redis: {
hosts: [{
host: '...',
port: Number
}],
options: {
// ...
}
}
});
// any redis command will be applicableRedis Sentinel plugin
NOTE: you can use only 1 of the plugins for redis - either cluster or sentinel
When using this plugin, make sure you also do npm i ioredis -S
Enables redisCluster communication based on ioredis module.
Allows one to setup connection to redis and communicate with it in a highly available fashion;
Events are emitted when plugin has completed connecting, or disconnecting. First arg is the transport instance
plugin:connect:redisSentinelplugin:close:redisSentinel
const userService = new UserService({
plugins: [ 'redisSentinel' ],
redis: {
sentinels: [{
host: '...',
port: Number
}],
name: 'mservice',
options: {
// ...
}
}
});Elasticsearch plugin
When using this plugin, make sure you also do npm i elasticsearch -S
Enables to use Elasticsearch as a NoSQL storage/search engine. Wraps an official Elasticsearch JavaScript API module.
Events are emitted when plugin has completed connecting, or disconnecting. First arg is the transport instance
plugin:connect:elasticsearchplugin:close:elasticsearch
const userService = new UserService({
plugins: [ 'elasticsearch' ],
elasticsearch: {
host: 'example.elastic.search:9200',
apiVersion: '2.1',
//...
}
});Cassandra plugin
When using this plugin, make sure you also do npm i express-cassandra -S
Enables to use Cassandra as a NoSQL storage/search engine. Based on express-cassandra module.
Events are emitted when plugin has completed connecting, or disconnecting. First arg is the transport instance
plugin:connect:cassandraplugin:close:cassandra
cassandra = require('express-cassandra');
const service = new Service({
plugins: [ 'cassandra' ],
cassandra: {
service: {
// models also can be path to directory with models
// https://github.com/masumsoft/express-cassandra#write-a-model-named-personmodeljs-inside-models-directory
models: {
Foo: {
fields:{
bar: 'text'
},
key:['bar']
}
}
},
client: {
clientOptions: {
contactPoints: ['cassandra.srv'],
protocolOptions: {
port: 9042
},
keyspace: 'mykeyspace',
queryOptions: {
consistency: cassandra.consistencies.one
}
},
ormOptions: {
defaultReplicationStrategy : {
class: 'SimpleStrategy',
replication_factor: 1
},
dropTableOnSchemaChange: false,
createKeyspace: true
}
}
});Http plugin
Features
- Allows creating
httpserver - Predefined handlers support
Handlers
You can use one of predefined handlers in /src/plugins/http/handlers directory
Allowed handlers at this moment:
- express (make sure you also do
npm i express -S) - restify (make sure you also do
npm i restify -S) - hapi (make sure you also do
npm i hapi -S, also additional dependencies may be required, for example if you want to use some of hapi's plugins)
Peer dependencies
npm i server-destroy -S
Events
plugin:start:httpplugin:stop:http
Usage
const service = new Service({
plugins: [ 'http' ],
http: {
server: {
attachSocketIO: false, // if true socketio plugin need to be included
handler: 'restify',
handlerConfig: {},
port: 3000,
}
}
});Hapi features
That's possible to use hapi plugins such as vision, bell, etc. All you need is extend the config of http server. Possible options are:
const service = new Service({
plugins: [ 'http' ],
http: {
server: {
handler: 'hapi',
handlerConfig: {
/** implicitly loads 'vision' plugin and decorates a native hapi request with 'sendView' method
* https://github.com/hapijs/vision
*/
views: {
engines: {
hbs: require('handlebars'),
},
paths: 'path/to/templates',
relativeTo: __dirname,
},
plugins: {
list: [{
// you can provide a plugin name, but be sure you've included it in the dependencies
register: 'bell',
options: {
/** bell options */
}
}, {
// also you can provide a function as a plugin
register: require('path/to/custom/plugin'),
options: {
/** options */
}
}, {
// or even just a path to the file
register: 'path/to/custom/plugin',
options: {}
}],
options: {
/** https://hapijs.com/api#plugins */
}
}
},
port: 3000,
}
}
});
// next in route handler you can use a native hapi request instance.
/** file: some/action/handler.js */
module.exports = function actionHandler(request) {
const context = {
example: true,
};
return request.transportRequest.sendView('view', context);
}
// decorates a native hapi request with 'redirect' method.
/** file: redirect/action/handler.js */
module.exports = function redirectHandler(request) {
return request.transportRequest.redirect('https://github.com/makeomatic');
}Socket.io plugin
Features
Attach Socket.io instance to .socketIO property.
Config
routerenabled-boolean, enable router, defaultfalse
options-object,socket.iooptionsadapter-object, adaptername-string, adapter name, e.g.amqpoptions-object, adapter options
Peer dependencies
npm i socket.io -Snpm i ms-socket.io-adapter-amqp -S
Usage
const service = new Service({
plugins: [ 'socketio' ],
socketio: {
router: {
enabled: true,
},
options: {
// socket.io options
},
}
});
// service.socketIO - Socket.io instanceRouter plugin
Attach router to service that can be used by other plugins
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago