Releases: moleculerjs/moleculer
v0.12.7
v0.12.6
Changes
- update dependencies
- The
breakLength
is changed toInfinity
(single-line printing) for better log processing when logger prints objects and arrays. - adds ability to customise console object/array printing #285
const util = require("util"); const broker = new ServiceBroker({ logger: true, logObjectPrinter: o => util.inspect(o, { depth: 4, colors: false, breakLength: 50 }) // `breakLength: 50` activates multi-line object });
v0.12.5
v0.12.4
New
Graceful shutdown
Thanks for @rmccallum81, ServiceBroker supports graceful shutdown. You can enable it with trackContext
broker option. If you enable it, all services wait for all running contexts before shutdowning. You can also define a timeout value with gracefulStopTimeout
broker option.
const broker = new ServiceBroker({
trackContext: true,
gracefulStopTimeout: 5 * 1000 // waiting max 5 sec
});
This timeout can be overwrite in service settings with $gracefulStopTimeout
property.
Changes
- fix service registry update after reconnecting. #262
- update index.d.ts
- update dependencies
- fix distributed timeout handling
v0.12.3
v0.12.2
New
Latency strategy
This strategy selects a node which has the lowest latency, measured by periodic PING
. Notice that the strategy only ping one of nodes from a single host. Due to the node list can be very long, it gets samples and selects the host with the lowest latency from only samples instead of the whole node list.
Usage
let broker = new ServiceBroker({
registry: {
strategy: "Latency"
}
});
Strategy options
Name | Type | Default | Description |
---|---|---|---|
sampleCount |
Number |
5 |
the number of samples. If you have a lot of hosts/nodes, it's recommended to increase the value. |
lowLatency |
Number |
10 |
the low latency (ms). The node which has lower latency than this value is selected immediately. |
collectCount |
Number |
5 |
the number of measured latency per host to keep in order to calculate the average latency. |
pingInterval |
Number |
10 |
ping interval (s). If you have a lot of host/nodes, it's recommended to increase the value. |
Usage with custom options
let broker = new ServiceBroker({
registry: {
strategy: "Latency",
strategyOptions: {
sampleCount: 15,
lowLatency: 20,
collectCount: 10,
pingInterval: 15
}
}
});
Thanks for @zllovesuki!
Filemask for Moleculer Runner
There is a new Moleculer Runner option --mask
to define filemask when load all services from folders.
Example
$ moleculer-runner.js -r --mask **/user*.service.js examples
Example to load Typescript services
$ node -r ts-node/register node_modules/moleculer/bin/moleculer-runner --hot --repl --mask **/*.service.ts services
Changes
- fix
d.ts
issues - fix event
group
handling in mixins (#217) - move
mergeSchemas
fromutils
toService
static method. It can be overwritten in a custom ServiceFactory - improve
d.ts
- fix
prefix
option in Redis Cacher (223) - remove
nanomatch
dependency, use own implementation - fix ContextFactory issue (235)
- expose utility functions as
require("moleculer").Utils
- overwritable
mergeSchemas
static method inService
class. - Moleculer Runner precedence order is changed. The
SERVICES
&SERVICEDIR
env vars overwrites the paths in CLI arguments.
v0.12.0
This version contains the most changes in the history of Moleculer! More than 200 commits with 17k additions and a lot of new features.
Breaking changes
Github organization is renamed
The Github organization name (Ice Services) has been renamed to MoleculerJS. Please update your bookmarks.
- Github organization: https://github.com/moleculerjs
- Website: https://moleculer.services or http://moleculerjs.com/
- Gitter chat: https://gitter.im/moleculerjs/moleculer
Mixin merging logic is changed
To support #188, mixin merging logic is changed at actions
. Now it uses defaultsDeep
for merging. It means you can extend the actions definition of mixins, no need to redeclare the handler
.
Add extra action properties but handler
is untouched
// mixin.service.js
module.exports = {
actions: {
create(ctx) {
// Action handler without `params`
}
}
};
// my.service.js
module.exports = {
mixins: [MixinService]
actions: {
create: {
// Add only `params` property to the `create` action
// The handler is merged from mixin
params: {
name: "string"
}
}
}
};
Wrapper removed from transporter options
If you are using transporter options, you will need to migrate them. The transporter specific wrapper has been removed from options (nats
, redis
, mqtt
, amqp
).
Before
// NATS transporter
const broker = new ServiceBroker({
transporter: {
type: "NATS",
options: {
nats: {
user: "admin",
pass: "1234"
}
}
}
});
// Redis transporter
const broker = new ServiceBroker({
transporter: {
type: "Redis",
options: {
redis: {
port: 6379,
db: 0
}
}
}
});
// MQTT transporter
const broker = new ServiceBroker({
transporter: {
type: "MQTT",
options: {
mqtt: {
user: "admin",
pass: "1234"
}
}
}
});
// AMQP transporter
const broker = new ServiceBroker({
transporter: {
type: "AMQP",
options: {
amqp: {
prefetch: 1
}
}
}
});
After
// NATS transporter
const broker = new ServiceBroker({
transporter: {
type: "NATS",
options: {
user: "admin",
pass: "1234"
}
}
});
// Redis transporter
const broker = new ServiceBroker({
transporter: {
type: "Redis",
options: {
port: 6379,
db: 0
}
}
});
// MQTT transporter
const broker = new ServiceBroker({
transporter: {
type: "MQTT",
options: {
user: "admin",
pass: "1234"
}
}
});
// AMQP transporter
const broker = new ServiceBroker({
transporter: {
type: "AMQP",
options: {
prefetch: 1
}
}
});
Default nodeID
generator changed
When nodeID
didn't define in broker options, the broker generated it from hostname (os.hostname()
). It could cause problem for new users when they tried to start multiple instances on the same computer. Therefore, the broker generates nodeID
from hostname and process PID. The newly generated nodeID looks like server-6874
where server
is the hostname and 6874
is the PID.
Protocol changed
The transport protocol is changed. The new version is 3
. Check the changes.
It means, the >=0.12.x versions can't communicate with old <=0.11 versions.
Changes:
- the
RESPONSE
packet has a new fieldmeta
. - the
EVENT
packet has a new fieldbroadcast
. - the
port
field is removed fromINFO
packet. - the
INFO
packet has a new fieldhostname
.
New features
New ServiceBroker options
There are some new properties in ServiceBroker option: middlewares
, created
, started
, stopped
.
They can be useful when you use broker config file and start your project with Moleculer Runner.
// moleculer.config.js
module.exports = {
logger: true,
// Add middlewares
middlewares: [myMiddleware()],
// Fired when the broker created
created(broker) {
},
// Fired when the broker started
started(broker) {
// You can return Promise
return broker.Promise.resolve();
},
// Fired when the broker stopped
stopped(broker) {
// You can return Promise
return broker.Promise.resolve();
}
};
Broadcast events with group filter
The broker.broadcast
function has a third groups
argument similar to broker.emit
.
// Send to all "mail" service instances
broker.broadcast("user.created", { user }, "mail");
// Send to all "user" & "purchase" service instances.
broker.broadcast("user.created", { user }, ["user", "purchase"]);
CPU usage-based strategy
There is a new CpuUsageStrategy
strategy. It selects a node which has the lowest CPU usage.
Due to the node list can be very long, it gets samples and selects the node with the lowest CPU usage from only samples instead of the whole node list.
There are 2 options for the strategy:
sampleCount
: the number of samples. Default:3
lowCpuUsage
: the low CPU usage percent. The node which has lower CPU usage than this value is selected immediately. Default:10
Usage:
const broker = new ServiceBroker({
registry: {
strategy: "CpuUsage"
}
});
Usage with custom options
const broker = new ServiceBroker({
registry: {
strategy: "CpuUsage",
strategyOptions: {
sampleCount: 3,
lowCpuUsage: 10
}
}
});
Starting logic is changed
The broker & services starting logic has been changed.
Previous logic: the broker starts transporter connecting. When it's done, it starts all services (calls service started
handlers). It has a disadvantage because other nodes can send requests to these services, while they are still starting and not ready yet.
New logic: the broker starts transporter connecting but it doesn't publish the local service list to remote nodes. When it's done, it starts all services (calls service started
handlers). Once all services start successfully, broker publishes the local service list to remote nodes. Hence other nodes send requests only after all local service started properly.
Please note: you can make dead-locks when two services wait for each other. E.g.:
users
service hasdependencies: [posts]
andposts
service hasdependencies: [users]
. To avoid it remove the concerned service fromdependencies
and usewaitForServices
method out ofstarted
handler instead.
Metadata is sent back to requester
At requests, ctx.meta
is sent back to the caller service. You can use it to send extra meta information back to the caller.
E.g.: send response headers back to API gateway or set resolved logged in user to metadata.
Export & download a file with API gateway:
// Export data
export(ctx) {
const rows = this.adapter.find({});
// Set response headers to download it as a file
ctx.meta.headers = {
"Content-Type": "application/json; charset=utf-8",
"Content-Disposition": 'attachment; filename=\"book.json\"'
}
return rows;
}
Authenticate:
auth(ctx) {
let user = this.getUserByJWT(ctx.params.token);
if (ctx.meta.user) {
ctx.meta.user = user;
return true;
}
throw new Forbidden();
}
Better ES6 class support
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
andevents
handlers as class methods. Call theparseServiceSchema
method in constructor with schema definition where the handlers pointed to these class methods.const Service = require("moleculer").Service; class GreeterService extends Service { constructor(broker) { super(broker); this.parseServiceSchema({ name: "greeter", version: "v2", meta: { scalable: true }, dependencies: [ "auth", "users" ], settings: { upperCase: true }, actions: { hello: this.hello, welcome: { cache: { keys: ["name"] }, params: { name: "string" }, handler: this.welcome } }, events: { "user.created": this.userCreated }, created: this.serviceCreated, started: this.serviceStarted, stopped: this.serviceStopped, }); } // Action handler hello() { return "Hello Moleculer"; } // Action handler welcome(ctx) { ...
v0.11.10
New
Built-in clustering in Moleculer Runner #169
By @tinchoz49 Moleculer Runner has a new built-in clustering function. With it, you can start multiple instances from your broker.
Example to start all services from the services
folder in 4 instances.
$ moleculer-runner --instances 4 services
Please note, the
nodeID
will be suffixed with the worker ID.
Context meta & params in metrics events #166
By @dani8art you can set that the broker put some ctx.meta
and ctx.params
fields to the metrics events.
You can define it in the action definition:
module.exports = {
name: "test",
actions: {
import: {
cache: true,
metrics: {
// Disable to add `ctx.params` to metrics payload. Default: false
params: false,
// Enable to add `ctx.meta` to metrics payload. Default: true
meta: true
},
handler(ctx) {
// ...
}
}
}
}
If the value is true
, it adds all fields. If Array
, it adds the specified fields. If Function
, it calls with params
or meta
and you need to return with an Object
.
v0.11.9
New
Strategy resolver
ServiceBroker can resolve the strategy
from a string.
let broker = new ServiceBroker({
registry: {
strategy: "Random"
// strategy: "RoundRobin"
}
});
You can set it via env variables as well, if you are using the Moleculer Runner:
$ REGISTRY_STRATEGY=random
Load env files in Moleculer Runner #158
Moleculer runner can load .env
file at starting. There are two new cli options to load env file:
-e, --env
- Load envorinment variables from the '.env' file from the current folder.-E, --envfile <filename>
- Load envorinment variables from the specified file.
Example
# Load the default .env file from current directory
$ moleculer-runner --env
# Load the specified .my-env file
$ moleculer-runner --envfile .my-env
Fixes
- fixed hot reloading after broken service files by @askuzminov (#155)
- allow fallbackResponse to be falsy values
v0.11.6
New
New cacher features
In action cache keys you can use meta keys with #
prefix.
broker.createService({
name: "posts",
actions: {
list: {
cache: {
// Cache key: "limit" & "offset" from ctx.params, "user.id" from ctx.meta
keys: ["limit", "offset", "#user.id"],
ttl: 5
},
handler(ctx) {...}
}
}
});
You can override the cacher default TTL setting in action definition.
let broker = new ServiceBroker({
cacher: {
type: "memory",
options: {
ttl: 30 // 30 seconds
}
}
});
broker.createService({
name: "posts",
actions: {
list: {
cache: {
// This cache entries will be expired after 5 seconds instead of 30.
ttl: 5
},
handler(ctx) {...}
}
}
});
You can change the built-in cacher keygen function to your own one.
let broker = new ServiceBroker({
cacher: {
type: "memory",
options: {
keygen(name, params, meta, keys) {
// Generate a cache key
return ...;
}
}
}
});
Others
d.ts
has been improved by @rmccallum81