The Service represents a microservice in the Moleculer. You can define actions and subscribe to events. To create a service you need to define a schema. The service schema is similar to a component of VueJS.
Schema
The schema has some main parts: name
, version
, settings
, actions
, methods
, events
.
Simple service schema to define two actions
{ |
Base properties
The Service has some base properties in the schema.
{ |
The name
is a mandatory property so it must be defined. It’s the first part of action name when you call it with broker.call
.
To disable service name prefixing set
$noServiceNamePrefix: true
in Service settings.
The version
is an optional property. Use it to run multiple version from the same service. It is a prefix in the actionName. It can be a Number
or a String
.
{ |
You can call this find
action on version 2
service:
broker.call("v2.posts.find"); |
REST callIf you are using our Moleculer Web module, you can request it as
GET /v2/posts/find
.
To disable version prefixing set
$noVersionPrefix: true
in Service settings.
Settings
The settings
property is a store, where you can store every settings/options to your service. You can reach it via this.settings
inside the service.
{ |
The
settings
is also obtainable on remote nodes. It is transferred during service discovering.
Internal settings
There are some internal settings which are used by core modules. These setting names start with $
(dollar sign).
Name | Type | Default | Description |
---|---|---|---|
$noVersionPrefix |
Boolean |
false |
Disable version prefixing in action names. |
$noServiceNamePrefix |
Boolean |
false |
Disable service name prefixing in action names. |
$dependencyTimeout |
Number |
0 |
Timeout for dependency waiting. |
Mixins
Mixins are a flexible way to distribute reusable functionalities for Moleculer services. The Service constructor merges these mixins with the current schema. It is to extend an other service in your service. When a service uses mixins, all properties in the mixin will be “mixed” into the current service.
Example how to extend moleculer-web
service
const ApiGwService = require("moleculer-web"); |
The above example creates an api
service which inherits all from ApiGwService
but overwrite the port setting and extend it with a new myAction
action.
Merge algorithm
The merge algorithm depends on the property type.
Property | Algorithm |
---|---|
name , version |
Merge & overwrite. |
settings |
Extend with defaultsDeep. |
actions |
Extend with defaultsDeep. You can disable an action from mixin if you set to false in your service. |
methods |
Merge & overwrite. |
events |
Concatenate listeners. |
created , started , stopped |
Concatenate listeners. |
mixins |
Concatenate listeners. |
any other | Merge & overwrite. |
Merge algorithm examplesMerge & overwrite: if serviceA has
a: 5
,b: 8
and serviceB hasc: 10
,b: 15
, the mixed service will havea: 5
,b: 15
andc: 10
.
Concatenate: if serviceA & serviceB subscribe tousers.created
event, both event handler will be called when theusers.created
event emitted.
Actions
The actions are the callable/public methods of the service. They are callable with broker.call
.
The action could be a function (shorthand for handler) or an object with some properties above all with the handler
.
The actions should be placed under the actions
key in the schema.
module.exports = { |
You can call the above actions as
const res = await broker.call("math.add", { a: 5, b: 7 }); |
Inside the action you can call other nested actions in other services with ctx.call
method. It is an alias to broker.call
, just set itself as parent context (due tracing).
module.exports = { |
In handlers the
this
is always pointed to the Service instance.
Events
You can subscribe to events under the events
key.
module.exports = { |
In handlers the
this
is always pointed to the Service instance.
Grouping
The broker groups the event listeners by group name. By default, The group name is the service name. But you can change it in the event definition.
module.exports = { |
Methods
You can also create private methods in the Service. They are under the methods
key. These functions are private, can’t be called with broker.call
. But you can call it inside service (from action handlers, event handlers and lifecycle event handlers).
Usage
module.exports = { |
The name of the method can’t be
name
,version
,settings
,schema
,broker
,actions
,logger
, because these words are reserved in the schema.
In methods the
this
is always pointed to the Service instance.
Lifecycle events
There are some lifecycle service events, that will be triggered by broker.
module.exports = { |
Dependencies
If your service depends on other services, use the dependencies
property in the schema. The service can wait for other services before starting. It uses the broker waitForServices
method.
module.exports = { |
The started
service handler is called once the likes
, users
and comments
services are available (either the local or remote nodes).
Metadata
The Service
schema has a metadata
property. You can store here any meta information about service. You can access it as this.metadata
inside service functions.
Moleculer modules don’t use it. You can store it whatever you want.
module.exports = { |
The
metadata
is transferred among other nodes, you can access it via$node.services
on other nodes.
Properties of this
In service functions, this
is always pointed to the Service instance. It has some properties & methods which you can use in your service functions.
Name | Type | Description |
---|---|---|
this.name |
String |
Name of service (from schema) |
this.version |
Number or String |
Version of service (from schema) |
this.settings |
Object |
Settings of service (from schema) |
this.metadata |
Object |
Metadata of service (from schema) |
this.schema |
Object |
Schema definition of service |
this.broker |
ServiceBroker |
Instance of broker |
this.Promise |
Promise |
Class of Promise (Bluebird) |
this.logger |
Logger |
Logger instance |
this.actions |
Object |
Actions of service. Service can call own actions directly but it is not recommended. Use the ctx.call instead! |
this.waitForServices |
Function |
Link to ‘broker.waitForServices’ method |
Create a service
There are several ways to create and load a service.
broker.createService()
Call the broker.createService
method with the schema of service as the first argument. It’s simple & fast. Use it when you are developing or prototyping.
broker.createService({ |
Load service from file
The recommended way is to place your service code into a single file and load it with the broker.
// Export the schema of service |
Load it with broker:
// Create broker |
In the service file you can also create the Service instance. In this case, you have to export a function which returns the instance of Service.
const { Service } = require("moleculer"); |
Or create a function which returns with the schema of service
// Export a function, the `loadService` will call with the ServiceBroker instance. |
Load multiple services from a folder
If you have many services (and you will have) we suggest to put them to a services
folder and load all of them with the broker.loadServices
method.
Syntax
broker.loadServices(folder = "./services", fileMask = "**/*.service.js"); |
Example
// Load every *.service.js file from the "./services" folder (including subfolders) |
Load with Moleculer Runner (recommended)
We recommend to use the Moleculer Runner to start a ServiceBroker and load services. Read more about Moleculer Runner. It is the easiest way to start a node.
Hot reloading services
When you are developing your microservices project would be useful a hot reload function which reloads your services when you modify it. Moleculer has a built-in hot-reloading function. You can enable it in broker options or in Moleculer Runner.
Demo video how it works.
Usage
let broker = new ServiceBroker({ |
Usage with Moleculer Runner
Turn it on with --hot
or -H
flags.
$ moleculer-runner --hot ./services/test.service.js |
Hot reloading function is working only with Moleculer Runner or if you load your services with
broker.loadService
orbroker.loadServices
. It doesn’t work withbroker.createService
.
Hot reloading is only watch the
service.js
file. If you are using additional JS files in your services and they are changed, broker won’t detect it. In this case it is better to use nodemon to restart all services and broker.
Local variables
If you would like to use local properties/variables in your service, declare them in the created
event handler.
Example for local variables
const http = require("http"); |
Naming restrictionIt is important to be aware that you can’t use variable name which is reserved for service or coincides with your method names! E.g.
this.name
,this.version
,this.settings
,this.schema
…etc.
ES6 classes
If you like better ES6 classes than Moleculer service schema, you can write your services in ES6 classes. There are two ways to do it.
Native ES6 classes with schema parsing
Define actions
and events
handlers as class methods. Call the parseServiceSchema
method in constructor with schema definition where the handlers pointed to these class methods.
const Service = require("moleculer").Service; |
Use decorators
Thanks for @ColonelBundy, you can use ES7/TS decorators as well: moleculer-decorators
Need a compilerPlease note, you need to use Typescript or Babel to compile decorators.
Example service
const moleculer = require('moleculer'); |