Migration guide from 0.14 to 0.15
Breaking changes
Minimum Node 18
The minimum supported Node version is changed from Node 10 to Node 18.
Communication protocol has been changed
The Moleculer communication protocol has been changed. The new protocol version is 5. However all schema-based serializer has been removed from the core repo. It means v0.15 Moleculer nodes will able to communicate with v0.14 nodes, if you disable version checking in broker options.
Schema-based serializers (ProtoBuf, Avro, Thrift) are removed
The reason is desribed in this issue: #882
If you use one of those, you should change it to one of these schemaless serializers: MsgPack, Notepack.io, JSON, JSONExt, CBOR
EventLegacy tracing export is removed
The EventLegacy tracing exporter is removed. Use the Event tracing exporter instead.
Legacy event handler is removed
The legacy event handler signature (user.created(payload, sender, eventName)) is removed. You should use the new Context based signature which was introduced in version 0.14.
Legacy event handler
module.exports = {
name: "accounts",
events: {
"user.created"(payload, sender, eventName) {
// ...
}
}
};Supported event handler
module.exports = {
name: "accounts",
events: {
"user.created"(ctx) {
console.log("Payload:", ctx.params);
console.log("Sender:", ctx.nodeID);
console.log("We have also metadata:", ctx.meta);
console.log("The called event name:", ctx.eventName);
// ...
}
}
};New REPL options
In order to the REPL options can be more extensible, a new replOptions broker option is introduces. You can use it instead of the old replCommands and replDelimiter broker options.
Old REPL options
// moleculer.config.js
module.exports = {
replDelimiter: "mol # ",
replCommands: [
{
command: "hello <name>",
action(broker, args) {
// ...
}
}
]
}New REPL options
// moleculer.config.js
module.exports = {
replOptions: {
delimiter: "mol # ",
customCommands: [
{
command: "hello <name>",
action(broker, args) {
// ...
}
}
]
}
}Please note, you should rename the
replCommandsproperty tocustomCommands, as well.
Action streaming
The built-in Stream sending has been rewritten. Now it accepts params besides the Stream instance.
The Stream parameter moved from ctx.params into calling options under a stream property.
New way to send a stream with extra parameters
The stream instance is passed as a calling options, so you can use ctx.params as a normal action call.
ctx.call("file.save", { filename: "as.txt" }, { stream: fs.createReadStream() });New way to receive a stream
// file.service.js
module.exports = {
name: "file",
actions: {
save(ctx) {
// The stream is in Context directly
const stream = ctx.stream;
const s = fs.createWriteStream(ctx.params.filename);
stream.pipe(s);
}
}
};Removed deprecated functions and signatures
Removed deprecated broker.createService signature
The broker.createService second argument (for service schema extending) is removed. You should use the mixins in service schema.
Removed deprecated event sending method signature
In previous versions, the emit, broadcast and broadcastLocal methods accept a group String or groups as Array<String> as third arguments, instead of an opts.
This signature is removed, you should always pass an opts object as 3rd argument.
Removed deprecated middleware as a Function
We removed and old and deprecated middleware signature where the middleware was localAction function. Now ServiceBroker accepts middleware as Object only.
Removed deprecated getLocalService signature.
The broker.getLocalService supports only getLocalService(name|obj) without second version parameter. If you want to get a versioned service, use the v1.posts argument or as object { name: "posts", version: 1}
Removed Service constructor 3rd argument.
The Service constructor had a 3rd argument as schemaMods which was deprecated because you should use mixins instead modifier schemas.
Garbage collector and event-loop metrics removed
Since gc-stats and event-loop-stats native libraries are not maintained and they are not compatible with newer Node versions, they are removed from the built-in metrics.
Removed metrics:
process.gc.timeprocess.gc.total.timeprocess.gc.executed.totalprocess.eventloop.lag.minprocess.eventloop.lag.avgprocess.eventloop.lag.maxprocess.eventloop.lag.countprocess.internal.active.requests
Removed STAN (NATS Streaming) transporter
The STAN (NATS Streaming) transporter has been removed while it's deprecated and not supported by the NATS.io, as well. More info: https://nats-io.gitbook.io/legacy-nats-docs/nats-streaming-server-aka-stan
Rewritten Kafka transporter (based on kafkajs)
The previous kafka-node based transporter has been rewritten to a kafkajs based transporter. It means, you should migrate your Kafka Transporter options.
// moleculer.config.js
module.exports = {
transporter: {
type: "Kafka",
options: {
// KafkaClient options. More info: https://kafka.js.org/docs/configuration
client: {
brokers: [/*...*/]
},
// KafkaProducer options. More info: https://kafka.js.org/docs/producing#options
producer: {},
// ConsumerGroup options. More info: https://kafka.js.org/docs/consuming#a-name-options-a-options
consumer: {},
// Advanced options for `send`. More info: https://kafka.js.org/docs/producing#producing-messages
publish: {},
// Advanced message options for `send`. More info: https://kafka.js.org/docs/producing#message-structure
publishMessage: {
partition: 0
}
}
}
}About new configuration options, check this documentation: https://kafka.js.org/docs/configuration
Removed legacy NATS library (nats@1.x.x) implementation
The legacy nats@1.x.x transporter implementation is removed. This version supports only nats@2.x.x library.
The Fastest Validator options changed.
In 0.15 the useNewCustomCheckFunction default value is changed from false to true. It means, if you have old custom checker function in your parameter validation schemas, you should rewrite it to the new custom check function form.
You can see example about migration here: https://github.com/icebob/fastest-validator/blob/master/CHANGELOG.md#new-custom-function-signature
Rewritten Typescript definition files
The previously used huge one-file index.d.ts file has been rewritten and separated to multiple d.ts files, all are placed besides the source file. It may causes breaking changes in Typescript projects.
Other breaking changes
ServiceBroker.Promiseis removed. Usebroker.Promiseorthis.Promiseinside aService.
New features
New JSON Extended serializer
We implemented a new JSON serializer which unlike the native JSON serializer, it supports serializing Buffer, BigInt, Date, Map, Set and RegExp classes, as well.
Example
// moleculer.config.js
module.exports = {
serializer: "JSONExt"
}Custom extensions
You can extend the serializer with custom types.
Example to extend with a custom class serializing/deserializing
// MyClass.js
class MyClass {
constructor(a, b) {
this.a = a;
this.b = b;
}
}// moleculer.config.js
module.exports = {
serializer: {
type: "JSONExt",
options: {
customs: [
{
// This is the identifier of the custom type
prefix: "AB",
// This function checks the type of JSON value
check: v => v instanceof MyClass,
// Serialize the custom class properties to a String
serialize: v => v.a + "|" + v.b,
// Deserialize the JSON string to custom class instance and set properties
deserialize: v => {
const [a, b] = v.split("|");
return new MyClass(parseInt(a), b);
}
}
]
}
}
}New Request headers
We added a new headers property in calling options and Context class to store meta information for an action calling or an event emitting.
The difference between headers and meta is that the meta is always passed to all action calls in a chain and merged, the headers is transferred only to the actual action call and not passed to the nested calls.
Please note, header keys start with
$means internal header keys (e.g.$streamObjectMode). We recommend to don't use this prefix for your keys to avoid conflicts.
Set headers in action calls
broker.call("posts.list", { limit: 100 }, {
headers: {
customProp: "customValue"
}
});You can use the same way for event emitting or broadcasting.
Read headers inside action handler
// posts.service.js
module.exports = {
name: "posts",
actions: {
list(ctx) {
const customProp = ctx.headers.customProp;
}
}
};You can use the same way in event handlers.
Use header value in cache keys
You can add headers values to the cache keys as well. For this, use @ prefix
// posts.service.js
module.exports = {
name: "posts",
actions: {
list: {
cache: {
keys: [
"limit", // value from `ctx.params`
"#tenant", // value from `ctx.meta`
"@customProp" // value from `ctx.headers`
]
}
handler(ctx) {
const customProp = ctx.headers.customProp;
}
}
}
};Response headers
The Moleculer protocol supports headers in response, as well (ctx.responseHeaders). But in normal way, you can't access to them in your services because you don't have pointer to the returned Context instance. So at present, it can be used by middlewares only.
Other changes
Better error handling in event handlers.
!TODO!
Cacher changes
The getCacheKey and opts.keygen signature has been changed
Old signature: getCacheKey(actionName, params, meta, keys, actionKeygen)
New signature: getCacheKey(action, opts, ctx)
Added missingResponse option to cacher options
In 0.14, you could not make a difference between the result cached value is null or it's not in the cache. Because both way, the cacher.get responded with null.
In 0.15, if a cache key is not found in cache, it returns undefined by default, or you can change it with missingResponse option.
Example: using a custom symbol to detect missing entries
const missingSymbol = Symbol("MISSING");
// moleculer.config.js
module.exports = {
cacher: {
type: "Memory",
options: {
missingResponse: missingSymbol
}
}
}
// Get data from cache
const res = await cacher.get("not-existing-key");
if (res === cacher.opts.missingSymbol) {
console.log("It's not cached.");
}Cache key generation changed
There are some changes in the serialized values in the cache keys. In previous versions, the null and undefined values were serialized as null, and "null" as string also serialized to null.
In 0.15, string values are wrapped into quotes, the null is null and undefined is serialized as undefined, so similar serialized values.
These changes means the 0.15 cachers create different cache keys than 0.14 cachers.
Full Changelog: v0.14.33...v0.15.0-beta1