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
replCommands
property 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.time
process.gc.total.time
process.gc.executed.total
process.eventloop.lag.min
process.eventloop.lag.avg
process.eventloop.lag.max
process.eventloop.lag.count
process.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.Promise
is removed. Usebroker.Promise
orthis.Promise
inside 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