🚀 moleculerjs/moleculer - Release Notes
v0.14.35 (2024-11-06)
## What's Changed
* chore(peer-deps): allow to work with pino v9 by @jellydn in https://github.com/moleculerjs/moleculer/pull/1282
* Runner: log runner error through util.inspect by @PetrChalov in https://github.com/moleculerjs/moleculer/pull/1304
* fix: Update default type for ServiceSchema generic to Service. by @marceliwac in https://github.com/moleculerjs/moleculer/pull/1299
* fix: updated removePendingRequestByNodeID by @JS-AK in https://github.com/moleculerjs/moleculer/pull/1306
## New Contributors
* @jellydn made their first contribution in https://github.com/moleculerjs/moleculer/pull/1282
* @PetrChalov made their first contribution in https://github.com/moleculerjs/moleculer/pull/1304
* @JS-AK made their first contribution in https://github.com/moleculerjs/moleculer/pull/1306
**Full Changelog**: https://github.com/moleculerjs/moleculer/compare/v0.14.34...v0.14.35
v0.14.34 (2024-07-28)
## What's Changed
* feat: Expand the type for ServiceSchema to allow for typed lifecycle handlers by @marceliwac in https://github.com/moleculerjs/moleculer/pull/1272
* Fix runner use of moleculer.config function with default export by @shawnmcknight in https://github.com/moleculerjs/moleculer/pull/1284
* Improve broker error handler types by @shawnmcknight in https://github.com/moleculerjs/moleculer/pull/1286
* Don't plugging third-party Promise library for ioredis in RedisTransporter by @kuzalekon in https://github.com/moleculerjs/moleculer/pull/1290
* fixed numeric cache key issue by @icebob https://github.com/moleculerjs/moleculer/issues/1289
## New Contributors
* @marceliwac made their first contribution in https://github.com/moleculerjs/moleculer/pull/1272
* @kuzalekon made their first contribution in https://github.com/moleculerjs/moleculer/pull/1290
**Full Changelog**: https://github.com/moleculerjs/moleculer/compare/v0.14.33...v0.14.34
v0.15.0-beta1 (2024-05-06)
[**Migration guide from 0.14 to 0.15**](https://github.com/moleculerjs/moleculer/blob/next/docs/MIGRATION_GUIDE_0.15.md)
# 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: https://github.com/moleculerjs/moleculer/issues/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**
```js
module.exports = {
name: "accounts",
events: {
"user.created"(payload, sender, eventName) {
// ...
}
}
};
```
**Supported event handler**
```js
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**
```js
// moleculer.config.js
module.exports = {
replDelimiter: "mol # ",
replCommands: [
{
command: "hello ",
action(broker, args) {
// ...
}
}
]
}
```
**New REPL options**
```js
// moleculer.config.js
module.exports = {
replOptions: {
delimiter: "mol # ",
customCommands: [
{
command: "hello ",
action(broker, args) {
// ...
}
}
]
}
}
```
> Please note, you should rename the `replCommands` property to `customCommands`, 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.
```js
ctx.call("file.save", { filename: "as.txt" }, { stream: fs.createReadStream() });
```
### New way to receive a stream
```js
// 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` 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.
```js
// 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. Use `broker.Promise` or `this.Promise` inside a `Service`.
# 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
```js
// 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
```js
// MyClass.js
class MyClass {
constructor(a, b) {
this.a = a;
this.b = b;
}
}
```
```js
// 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
```js
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
```js
// 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
```js
// 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**
```js
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**: https://github.com/moleculerjs/moleculer/compare/v0.14.33...v0.15.0-beta1
v0.14.33 (2024-04-02)
## What's Changed
* autodetect Redis type discoverer when using redis SSL URI by @Freezystem in https://github.com/moleculerjs/moleculer/pull/1260
* Transit improve by @0x0a0d in https://github.com/moleculerjs/moleculer/pull/1258
* change from 'connect' to 'ready' event in redis clients. Fixes #1257 by @icebob in https://github.com/moleculerjs/moleculer/pull/1269
* Add hook middlewares interceptors to preserve call context with call middlewares. by @DonVietnam in https://github.com/moleculerjs/moleculer/pull/1270
* Remove unnecessary clone in node update method by @Ubitso in https://github.com/moleculerjs/moleculer/pull/1274
## New Contributors
* @Freezystem made their first contribution in https://github.com/moleculerjs/moleculer/pull/1260
* @DonVietnam made their first contribution in https://github.com/moleculerjs/moleculer/pull/1270
**Full Changelog**: https://github.com/moleculerjs/moleculer/compare/v0.14.32...v0.14.33
v0.14.32 (2023-11-12)
## What's Changed
* Update peer dependency for mqtt to 5.0.2 by @mze9412 in https://github.com/moleculerjs/moleculer/pull/1236
* add d.ts for class Runner (MoleculerRunner) by @0x0a0d in https://github.com/moleculerjs/moleculer/pull/1245
* Update index.d.ts with Middlewares.Transmit type definitions by @0x0a0d in https://github.com/moleculerjs/moleculer/pull/1246
* fix memory leak by @ghostiee in https://github.com/moleculerjs/moleculer/pull/1243
* imp(index.d.ts): middleware serviceCreating params by @0x0a0d in https://github.com/moleculerjs/moleculer/pull/1248
## New Contributors
* @mze9412 made their first contribution in https://github.com/moleculerjs/moleculer/pull/1236
* @ghostiee made their first contribution in https://github.com/moleculerjs/moleculer/pull/1243
**Full Changelog**: https://github.com/moleculerjs/moleculer/compare/v0.14.31...v0.14.32
v0.14.31 (2023-08-06)
## What's Changed
* Remove usage of _.uniq by @MrDroid1 in https://github.com/moleculerjs/moleculer/pull/1211
* Fix: prometheus reporter to accept host option by @MichaelErmer in https://github.com/moleculerjs/moleculer/pull/1221
* Bugfix: started not being called when createService is used by @MichaelErmer in https://github.com/moleculerjs/moleculer/pull/1229
## New Contributors
* @MichaelErmer made their first contribution in https://github.com/moleculerjs/moleculer/pull/1221
**Full Changelog**: https://github.com/moleculerjs/moleculer/compare/v0.14.30...v0.14.31
v0.14.30 (2023-07-15)
## What's Changed
* Improve logger types by @shawnmcknight in https://github.com/moleculerjs/moleculer/pull/1208
* add typings to package.json export by @cs4inctec in https://github.com/moleculerjs/moleculer/pull/1210
* Remove usage of _.random by @MrDroid1 in https://github.com/moleculerjs/moleculer/pull/1212
* replace deprecated redis.setex with redis.set method by @fernandodevelon in https://github.com/moleculerjs/moleculer/pull/1191
* Update some registry types around ActionCatalog by @shawnmcknight in https://github.com/moleculerjs/moleculer/pull/1225
## New Contributors
* @cs4inctec made their first contribution in https://github.com/moleculerjs/moleculer/pull/1210
* @MrDroid1 made their first contribution in https://github.com/moleculerjs/moleculer/pull/1212
* @fernandodevelon made their first contribution in https://github.com/moleculerjs/moleculer/pull/1191
**Full Changelog**: https://github.com/moleculerjs/moleculer/compare/v0.14.29...v0.14.30
v0.14.29 (2023-03-12)
## What's Changed
* Improve lifecycle handler types by @shawnmcknight in https://github.com/moleculerjs/moleculer/pull/1179
* chore(types): add service list options & define getActionList type by @lucduong in https://github.com/moleculerjs/moleculer/pull/1182
* fix: do not emit send node info during broker stopping event by @alvaroinckot in https://github.com/moleculerjs/moleculer/pull/1186
* Updated Datadog metrics by @bcavlin in https://github.com/moleculerjs/moleculer/pull/1156
* chore(types): mergeSchema can be used to merge 2 mixins by @0x0a0d in https://github.com/moleculerjs/moleculer/pull/1187
* Allow opt out of redlock in redis cacher by @shawnmcknight in https://github.com/moleculerjs/moleculer/pull/1192
## New Contributors
* @lucduong made their first contribution in https://github.com/moleculerjs/moleculer/pull/1182
* @bcavlin made their first contribution in https://github.com/moleculerjs/moleculer/pull/1156
**Full Changelog**: https://github.com/moleculerjs/moleculer/compare/v0.14.28...v0.14.29
v0.14.28 (2023-01-08)
## What's Changed
- fix no clean exit on shutdown, with disableBalancer: true [#1168](https://github.com/moleculerjs/moleculer/pull/1168)
- change `__proto__` to `Object.getProtoTypeOf` [#1170](https://github.com/moleculerjs/moleculer/pull/1170)
- fix merge schemas (handling nulls) [#1172](https://github.com/moleculerjs/moleculer/pull/1172)
- fix hot reload error handling [#1174](https://github.com/moleculerjs/moleculer/issues/1174)
- update d.ts file
- update dependencies
## New Contributors
* @danieledraganti made their first contribution in https://github.com/moleculerjs/moleculer/pull/1173
* @gautaz made their first contribution in https://github.com/moleculerjs/moleculer/pull/1170
**Full Changelog**: https://github.com/moleculerjs/moleculer/compare/v0.14.27...v0.14.28
v0.14.27 (2022-12-17)
## What's Changed
* feat(TS/cachers): add types for lock functions by @thib3113 in https://github.com/moleculerjs/moleculer/pull/1152
* Typing add spanName and safeTags to tracing options by @thib3113 in https://github.com/moleculerjs/moleculer/pull/1157
* Use interface instead of type to allow for declaration merging by @shawnmcknight in https://github.com/moleculerjs/moleculer/pull/1165
* Prevent registerInternalServices deprecation warning by @DenisFerrero in https://github.com/moleculerjs/moleculer/pull/1163
## New Contributors
* @DenisFerrero made their first contribution in https://github.com/moleculerjs/moleculer/pull/1163
**Full Changelog**: https://github.com/moleculerjs/moleculer/compare/v0.14.26...v0.14.27
v0.14.26 (2022-11-10)
## What's Changed
## Changes
- fix typescript definitions for the Service class [#1139](https://github.com/moleculerjs/moleculer/pull/1139)
- allow matching hooks to multiple actions with "|" [#1149](https://github.com/moleculerjs/moleculer/pull/1149)
- fix serializers datetime flaky test [#1151](https://github.com/moleculerjs/moleculer/pull/1151)
## New Contributors
* @sabadoryo made their first contribution in https://github.com/moleculerjs/moleculer/pull/1148
* @SKarajic made their first contribution in https://github.com/moleculerjs/moleculer/pull/1139
* @someone635 made their first contribution in https://github.com/moleculerjs/moleculer/pull/1149
* @sorattorafa made their first contribution in https://github.com/moleculerjs/moleculer/pull/1151
**Full Changelog**: https://github.com/moleculerjs/moleculer/compare/v0.14.25...v0.14.26
v0.14.25 (2022-10-29)
## Changes
- fix Node 19 compatibility
**Full Changelog**: https://github.com/moleculerjs/moleculer/compare/v0.14.24...v0.14.25
v0.14.24 (2022-10-11)
## Changes
- allow moleculer-runner to resolve configuration files from node_modules [#1126](https://github.com/moleculerjs/moleculer/pull/1126)
- fixed slower broker startup time issue [#1132](https://github.com/moleculerjs/moleculer/issues/1132)
- fixed memory leak at dynamic service creation [#1121](https://github.com/moleculerjs/moleculer/issues/1121)
- fixed invalid 'undefined' type in validator schema. [#1137](https://github.com/moleculerjs/moleculer/issues/1137)
- update dependencies
v0.14.23 (2022-08-16)
## Changes
- fixed timeout issue in `waitForServices` method [#1123](https://github.com/moleculerjs/moleculer/issues/1123)
- fixed metadata issue when compression enabled [#1122](https://github.com/moleculerjs/moleculer/issues/1122)
v0.14.22 (2022-08-13)
_35 commits from 11 contributors._
## Changes
- fixed 'Ctx is undefined when using shard strategy and preferLocal is false, throws error on emit' [#1072](https://github.com/moleculerjs/moleculer/issues/1072)
- fixed info packet send at broker stop [#1101](https://github.com/moleculerjs/moleculer/pull/1101)
- added support for either-or versions to waitForServices [#1030](https://github.com/moleculerjs/moleculer/pull/1030)
- fixed streaming issue with compression [#1100](https://github.com/moleculerjs/moleculer/issues/1100)
- add requestID to debug logs in transit [#1104](https://github.com/moleculerjs/moleculer/issues/1104)
- removed static on methods for the use of ServiceFactory [#1098](https://github.com/moleculerjs/moleculer/issues/1098)
- fixed the issue with setting tracing and metrics options with env variables [#1112](https://github.com/moleculerjs/moleculer/issues/1112)
- added dependencyTimeout broker option [#1118](https://github.com/moleculerjs/moleculer/issues/1118)
- improved d.ts [#1099](https://github.com/moleculerjs/moleculer/pull/1099) [#1111](https://github.com/moleculerjs/moleculer/pull/1111) [#1115](https://github.com/moleculerjs/moleculer/pull/1115)
- updated dependencies
v0.14.21 (2022-04-30)
_20 commits from 2 contributors._
## ESM support [#1063](https://github.com/moleculerjs/moleculer/issues/1063)
This version contains an ESM-based Moleculer Runner. This Runner is able to load ESM configuration file and ESM services. _It can load the CJS services, as well_
**Example usage**
```
moleculer-runner-esm --repl services/**/*.service.mjs
```
Moreover, the `index.js` file is wrapped into `index.mjs`, so you can import internal modules from the core in ESM modules. E.g.:
```js
import { ServiceBroker, Errors } from "moleculer";
```
Please note, **the hot-reload function doesn't work with this ESM Runner**. The cause: https://github.com/nodejs/modules/issues/307
Node maintainers try to solve the missing features (module cache and module dependency tree) with [loaders](https://nodejs.org/api/esm.html#loaders) but this API is not stable yet.
## Other Changes
- `broker.stopping` property is created to indicate that broker is in stopping state.
v0.14.20 (2022-04-19)
_52 commits from 8 contributors._
## Dependency logic changed [#1077](https://github.com/moleculerjs/moleculer/issues/1077)
In [mixed architecture](https://moleculer.services/docs/0.14/clustering.html#Mixed-architecture), it's not hard to create a circular service dependency that may cause a dead-lock during the start of Moleculer nodes. The problem is that Moleculer node only sends the local service registry to remote nodes after **all** local services started properly.
As of 0.14.20, this behavior has changed. The new logic uses a debounced registry sending method which is triggered every time a local service, that the node manages, has `started()`.
Note that the new method generates more [INFO packets](https://github.com/moleculer-framework/protocol/blob/master/4.0/PROTOCOL.md#info), than early versions, during the start of the node. The number of INFO packets depends on the number of the services that the node manages. The debounce timeout, between sending INFO packets, is 1 second.
## Other Changes
- fix ActionLogger and TransitLogger middlewares.
- update Datadog Logger using v2 API. [#1056](https://github.com/moleculerjs/moleculer/pull/1056)
- update dependencies.
- update d.ts file. [#1064](https://github.com/moleculerjs/moleculer/pull/1064), [#1073](https://github.com/moleculerjs/moleculer/pull/1073)
- fix pino child logger bindings. [#1075](https://github.com/moleculerjs/moleculer/pull/1075)
v0.14.19 (2022-01-08)
_69 commits from 7 contributors._
## Custom error recreation feature [#1017](https://github.com/moleculerjs/moleculer/pull/1017)
You can create a custom `Regenerator` class which is able to serialize and deserialize your custom errors. It's necessary when the custom error is created on a remote node and must be serialized to be able to sent back to the caller.
**Create a custom Regenerator**
```js
const { Regenerator, MoleculerError } = require("moleculer").Errors;
class TimestampedError extends MoleculerError {
constructor(message, code, type, data, timestamp) {
super(message, code, type, data);
this.timestamp = timestamp;
}
}
class CustomRegenerator extends Regenerator {
restoreCustomError(plainError, payload) {
const { name, message, code, type, data, timestamp } = plainError;
switch (name) {
case "TimestampedError":
return new TimestampedError(message, code, type, data, timestamp);
}
}
extractPlainError(err) {
return {
...super.extractPlainError(err),
timestamp: err.timestamp
};
}
}
module.exports = CustomRegenerator;
```
**Use it in broker options**
```js
// moleculer.config.js
const CustomRegenerator = require("./custom-regenerator");
module.exports = {
errorRegenerator: new CustomRegenerator()
}
```
## Error events [#1048](https://github.com/moleculerjs/moleculer/pull/1048)
When an error occured inside ServiceBroker, it's printed to the console, but there was no option that you can process it programatically (e.g. transfer to an external monitoring service). This feature solves it. Every error inside ServiceBroker broadcasts a **local** (not transported) event (`$transporter.error`, `$broker.error`, `$transit.error`, `$cacher.error`, `$discoverer.error`) what you can listen in your dedicated service or in a middleware.
**Example to listen in an error-tracker service**
```js
module.exports = {
name: "error-tracker",
events: {
"$**.error": {
handler(ctx) {
// Send the error to the tracker
this.sendError(ctx.params.error);
}
}
}
}
```
**Example to listen in a middleware or in broker options**
```js
module.exports = {
created(broker) {
broker.localBus.on("*.error", payload => {
// Send the error to the tracker
this.sendError(payload.error);
});
}
}
```
## Wildcards in Action Hooks [#1051](https://github.com/moleculerjs/moleculer/pull/1051)
You can use `*` wildcard in action names when you use it in Action Hooks.
**Example**
```js
hooks: {
before: {
// Applies to all actions that start with "create-"
"create-*": [],
// Applies to all actions that end with "-user"
"*-user": [],
}
}
```
## Other Changes
- update dependencies.
- update d.ts file. [#1025](https://github.com/moleculerjs/moleculer/pull/1025), [#1028](https://github.com/moleculerjs/moleculer/pull/1028), [#1032](https://github.com/moleculerjs/moleculer/pull/1032)
- add `safetyTags` option to tracing exporters. [#1052](https://github.com/moleculerjs/moleculer/pull/1052)
v0.14.18 (2021-10-20)
_20 commits from 7 contributors._
## Changes
- update dependencies.
- expose Cacher and Validator middlewares. [#1012](https://github.com/moleculerjs/moleculer/pull/1012)
- update d.ts file. [#1013](https://github.com/moleculerjs/moleculer/pull/1013)
- parse user & password from NATS server urls. [#1021](https://github.com/moleculerjs/moleculer/pull/1021)
v0.14.17 (2021-09-13)
_61 commits from 10 contributors._
## Changes
- reformat codebase with Prettier.
- fix binding issue in Pino logger. [#974](https://github.com/moleculerjs/moleculer/pull/974)
- update d.ts file. [#980](https://github.com/moleculerjs/moleculer/pull/980) [#970](https://github.com/moleculerjs/moleculer/pull/970)
- transit message handler promises are resolved. [#984](https://github.com/moleculerjs/moleculer/pull/984)
- fix cacher issue if cacher is not connected. [#987](https://github.com/moleculerjs/moleculer/pull/987)
- fix Jest open handlers issue. [#989](https://github.com/moleculerjs/moleculer/pull/989)
- fix cacher cloning issue. [#990](https://github.com/moleculerjs/moleculer/pull/990)
- add custom headers option to Zipkin trace exporter. [#993](https://github.com/moleculerjs/moleculer/pull/993)
- fix `heartbeatTimeout` option in BaseDiscoverer. [#985](https://github.com/moleculerjs/moleculer/pull/985)
- add cacher `keygen` option action definition. [#1004](https://github.com/moleculerjs/moleculer/pull/1004)
- update dependencies
v0.14.16 (2021-07-21)
_11 commits from 4 contributors._
## Changes
- fix `nats-streaming` version in peerDependencies.
- RedisCacher `pingInterval` option. [#961](https://github.com/moleculerjs/moleculer/pull/961)
- Update NATS transporter messages to debug. [#963](https://github.com/moleculerjs/moleculer/pull/963)
- update d.ts file. [#964](https://github.com/moleculerjs/moleculer/pull/964) [#966](https://github.com/moleculerjs/moleculer/pull/966)
- update dependencies
v0.14.15 (2021-07-10)
_15 commits from 5 contributors._
## Changes
- fix `nats` version in peerDependencies.
- convert `url` to `servers` in nats@2. [#954](https://github.com/moleculerjs/moleculer/pull/954)
- add typing for `mcall` `settled` option. [#957](https://github.com/moleculerjs/moleculer/pull/957)
- revert TS `ThisType` issue in 0.14.14. [#958](https://github.com/moleculerjs/moleculer/pull/958)
- update dependencies
- add `useTag259ForMaps: false` default option for CBOR serializer to keep the compatibility.
v0.14.14 (2021-06-27)
_105 commits from 11 contributors._
## New CBOR serializer [#905](https://github.com/moleculerjs/moleculer/pull/905)
CBOR ([cbor-x](https://github.com/kriszyp/cbor-x)) is a new serializer but faster than any other serializers.
**Example**
```js
// moleculer.config.js
module.exports = {
logger: true,
serializer: "CBOR"
};
```
**Benchmark**
```
Suite: Serialize packet with 10bytes
√ JSON 509,217 rps
√ Avro 308,711 rps
√ MsgPack 79,932 rps
√ ProtoBuf 435,183 rps
√ Thrift 93,324 rps
√ Notepack 530,121 rps
√ CBOR 1,016,135 rps
JSON (#) 0% (509,217 rps) (avg: 1μs)
Avro -39.38% (308,711 rps) (avg: 3μs)
MsgPack -84.3% (79,932 rps) (avg: 12μs)
ProtoBuf -14.54% (435,183 rps) (avg: 2μs)
Thrift -81.67% (93,324 rps) (avg: 10μs)
Notepack +4.11% (530,121 rps) (avg: 1μs)
CBOR +99.55% (1,016,135 rps) (avg: 984ns)
```
## `settled` option in `broker.mcall`
The `broker.mcall` method has a new `settled` option to receive all Promise results. Without this option, if you make a multi-call and one call is rejected, the response will be a rejected `Promise` and you don't know how many (and which) calls were rejected.
If `settled: true`, the method returns a resolved `Promise` in any case and the response contains the statuses and responses of all calls.
**Example**
```js
const res = await broker.mcall([
{ action: "posts.find", params: { limit: 2, offset: 0 },
{ action: "users.find", params: { limit: 2, sort: "username" } },
{ action: "service.notfound", params: { notfound: 1 } }
], { settled: true });
console.log(res);
```
The `res` will be something similar to
```js
[
{ status: "fulfilled", value: [/*... response of `posts.find`...*/] },
{ status: "fulfilled", value: [/*... response of `users.find`...*/] },
{ status: "rejected", reason: {/*... Rejected response/Error`...*/} }
]
```
## New `MOLECULER_CONFIG` environment variable in Runner
In the Moleculer Runner, you can configure the configuration filename and path with the `MOLECULER_CONFIG` environment variable. It means, no need to specify the config file with `--config` argument.
## Supporting `nats@2.x.x` in NATS transporter
The new nats `2.x.x` version has a new breaking API which has locked the NATS transporter for `nats@1.x.x` library. As of this release, the NATS transporter supports both major versions of the `nats` library.
_The transporter automatically detects the version of the library and uses the correct API._
### Async custom validator functions and `ctx` as metadata
Since `fastest-validator@1.11.0`, the FastestValidator supports async custom validators and you can [pass metadata for custom validator functions](https://github.com/icebob/fastest-validator/blob/master/CHANGELOG.md#meta-information-for-custom-validators).
In Moleculer, the `FastestValidator` passes the `ctx` as metadata. It means you can access to the current context, service, broker and you can make async calls (e.g calling another service) in custom checker functions.
**Example**
```js
// posts.service.js
module.exports = {
name: "posts",
actions: {
params: {
$$async: true,
owner: { type: "string", custom: async (value, errors, schema, name, parent, context) => {
const ctx = context.meta;
const res = await ctx.call("users.isValid", { id: value });
if (res !== true)
errors.push({ type: "invalidOwner", field: "owner", actual: value });
return value;
} },
},
/* ... */
}
}
```
## Changes
- fix node crash in encryption mode with TCP transporter. [#849](https://github.com/moleculerjs/moleculer/pull/849)
- expose `Utils` in typescript definition. [#909](https://github.com/moleculerjs/moleculer/pull/909)
- other d.ts improvements. [#920](https://github.com/moleculerjs/moleculer/pull/920), [#922](https://github.com/moleculerjs/moleculer/pull/922), [#934](https://github.com/moleculerjs/moleculer/pull/934), [#950](https://github.com/moleculerjs/moleculer/pull/950)
- fix etcd3 discoverer lease-loss issue [#922](https://github.com/moleculerjs/moleculer/pull/922)
- catch errors in Compression and Encryption middlewares. [#850](https://github.com/moleculerjs/moleculer/pull/850)
- using optional peer dependencies. [#911](https://github.com/moleculerjs/moleculer/pull/911)
- add relevant packet to to serialization and deserialization calls. [#932](https://github.com/moleculerjs/moleculer/pull/932)
- fix disabled balancer issue with external discoverer. [#933](https://github.com/moleculerjs/moleculer/pull/933)
v0.14.13 (2021-04-09)
## Changes _(62 commits from 12 contributors)_
- update dependencies
- logging if encryption middleware can't decrypt the data instead of crashing. [#853](https://github.com/moleculerjs/moleculer/pull/853)
- fix `disableHeartbeatChecks` option handling. [#858](https://github.com/moleculerjs/moleculer/pull/858)
- force scanning only master redis nodes for deletion. [#865](https://github.com/moleculerjs/moleculer/pull/865)
- add more info into `waitForServices` debug log messages. [#870](https://github.com/moleculerjs/moleculer/pull/870)
- fix `EVENT` packet Avro schema. [#856](https://github.com/moleculerjs/moleculer/issues/856)
- fix array & date conversion in cacher default key generator. [#883](https://github.com/moleculerjs/moleculer/issues/883)
- fix Datadog tracing exporter. [#890](https://github.com/moleculerjs/moleculer/issues/890)
- better elapsed time handling in tracing. [#899](https://github.com/moleculerjs/moleculer/issues/899)
- improve type definitions. [#843](https://github.com/moleculerjs/moleculer/pull/843), [#885](https://github.com/moleculerjs/moleculer/pull/885), [#886](https://github.com/moleculerjs/moleculer/pull/886)
- add E2E tests for CI (test all built-in transporter & serializers)
v0.14.12 (2021-01-03)
## Other changes
- update dependencies
- improved type definitions. [#816](https://github.com/moleculerjs/moleculer/pull/816) [#817](https://github.com/moleculerjs/moleculer/pull/817) [#834](https://github.com/moleculerjs/moleculer/pull/834) [#840](https://github.com/moleculerjs/moleculer/pull/840)
- support `rediss://` cacher URI. [#837](https://github.com/moleculerjs/moleculer/pull/837)
- fix Event Trace exporter generated events loop. [#836](https://github.com/moleculerjs/moleculer/pull/836)
- change log level of node disconnected message. [#838](https://github.com/moleculerjs/moleculer/pull/838)
- improve the `broker.waitForServices` response. [#843](https://github.com/moleculerjs/moleculer/pull/843)
- fix recursive hot-reload issue on Linux OS. [#848](https://github.com/moleculerjs/moleculer/pull/848)
v0.14.11 (2020-09-27)
## New `merged` service lifecycle hook
Service has a new `merged` lifecycle hook which is called after the service schemas (including mixins) has been merged but before service is registered. It means you can manipulate the merged service schema before it's processed.
**Example**
```js
// posts.service.js
module.exports = {
name: "posts",
settings: {},
actions: {
find: {
params: {
limit: "number"
}
handler(ctx) {
// ...
}
}
},
merged(schema) {
// Modify the service settings
schema.settings.myProp = "myValue";
// Modify the param validation schema in an action schema
schema.actions.find.params.offset = "number";
}
};
```
## Other changes
- add `requestID` tag to all action and event spans [#802](https://github.com/moleculerjs/moleculer/pull/802)
- fix bug in second level of mixins with $secureSettings [#811](https://github.com/moleculerjs/moleculer/pull/811)
v0.14.10 (2020-08-23)
## Changes
- update dependencies
- fix issues in index.d.ts
- fix broadcast event sending issue when `disableBalancer: true` [#799](https://github.com/moleculerjs/moleculer/pull/799) (thanks for [@ngraef](https://github.com/ngraef))
v0.14.9 (2020-08-06)
## Register method in module resolver
If you create a custom module (e.g. serializer), you can register it into the built-in modules with the `register` method. This method is also available in all other built-in module resolver.
**Example**
```js
// SafeJsonSerializer.js
const { Serializers } = require("moleculer");
class SafeJsonSerializer {}
Serializers.register("SafeJSON", SafeJSON);
module.exports = SafeJsonSerializer;
```
```js
// moleculer.config.js
require("./SafeJsonSerializer");
module.exports = {
nodeID: "node-100",
serializer: "SafeJSON"
// ...
});
```
## Changeable validation property name
You can change the `params` property name in validator options. It can be useful if you have a custom Validator implementation.
```js
const broker = new ServiceBroker({
validator: {
type: "Fastest",
options: {
paramName: "myParams" // using `myParams` instead of `params`
}
}
});
broker.createService({
name: "posts",
actions: {
create: {
myParams: {
title: "string"
}
},
handler(ctx) { /* ... */ }
}
});
```
## Global tracing span tags for actions & events
Thanks for [@kthompson23](https://github.com/kthompson23), you can configure the action & events tracing span tags globally. These tags will be used for all actions & events where tracing is enabled. Of course, you can overwrite them locally in the action & event schema.
**Example**
```js
// moleculer.config.js
module.exports = {
tracing: {
enabled: true,
exporter: 'Zipkin',
tags: {
action: {
meta: ['app.id', 'user.email', 'workspace.name'],
params: false, // overrides default behavior of all params being adding as tags
response: true,
},
event: (ctx) {
return {
caller: ctx.caller,
}
}
}
}
}
```
## Other changes
- fix multiple trace spans with same ID issue in case of retries.
- update dependencies
- add `lastValue` property to histogram metric type.
- update return type of context's copy method.
- add configuration hotReloadModules [#779](https://github.com/moleculerjs/moleculer/pull/779)
- Remove Zipkin v1 annotations and change kind to SERVER
v0.14.8 (2020-06-27)
## Github Sponsoring is available for Moleculer :tada:
We have been approved in Github Sponsors program, so you can sponsor the Moleculer project via [Github Sponsors](https://github.com/sponsors/moleculerjs).
_If you have taxing problem with Patreon, change to Github Sponsors._
## New Validator configuration
The `validator` has the same module configuration in broker options like other modules. It means you can configure the validation constructor options via broker options (moleculer.config.js).
**Default usage:**
```js
//moleculer.config.js
module.exports = {
nodeID: "node-100",
validator: true // Using the default Fastest Validator
}
```
**Using built-in validator name:**
```js
//moleculer.config.js
module.exports = {
nodeID: "node-100",
validator: "FastestValidator" // Using the Fastest Validator
}
```
**Example with options:**
```js
//moleculer.config.js
module.exports = {
nodeID: "node-100",
validator: {
type: "FastestValidator",
options: {
useNewCustomCheckerFunction: true,
defaults: { /*...*/ },
messages: { /*...*/ },
aliases: { /*...*/ }
}
}
}
```
**Example with custom validator**
```js
//moleculer.config.js
const BaseValidator = require("moleculer").Validators.Base;
class MyValidator extends BaseValidator {}
module.exports = {
nodeID: "node-100",
validator: new MyValidator()
}
```
## New metrics
Added the following new metrics:
- `moleculer.event.received.active`: Number of active event executions.
- `moleculer.event.received.error.total`: Number of event execution errors.
- `moleculer.event.received.time`: Execution time of events in milliseconds.
- `os.memory.total`: OS used memory size.
## Other changes
- support using `moleculer.config.js` with `export default`.
- remove some lodash methods.
- upgrade to the latest `tsd`.
- new `dependencyInterval` broker option. Using as default value for `broker.waitForServices` [#761](https://github.com/moleculerjs/moleculer/pull/761)
- fix Datadog traceID, spanID generation logic to work with latest `dd-trace`.
- add error stack trace to `EventLegacy` trace exporter.
- fix INFO key issue in Redis Discoverer after Redis server restarting.
v0.14.7 (2020-05-22)
## New Discoverer module
The Discoverer is a new built-in module in Moleculer framework. It's responsible for that all Moleculer nodes can discover each other and check them with heartbeats. In previous versions, it was an integrated module inside `ServiceRegistry` & `Transit` modules. In this version, the discovery logic has been extracted to a separated built-in module. It means you can replace it to other built-in implementations or a custom one. The current discovery & heartbeat logic is moved to the `Local` Discoverer.
Nevertheless, this version also contains other discoverers, like Redis & etcd3 discoverers. Both of them require an external server to make them work.
One of the main advantages of the external discoverers, the node discovery & heartbeat packets don't overload the communication on the transporter. The transporter transfers only the request, response, event packets.
By the way, the external discoverers have some disadvantages, as well. These discoverers can detect lazier the new and disconnected nodes because they scan the heartbeat keys periodically on the remote Redis/etcd3 server. The period of checks depends on the `heartbeatInterval` broker option.
>The Local Discoverer (which is the default) works like the discovery of previous versions, so if you want to keep the original logic, you'll have to do nothing.
>Please note the TCP transporter uses Gossip protocol & UDP packets for discovery & heartbeats, it means it can work only with Local Discoverer.
### Local Discoverer
It's the default Discoverer, it uses the transporter module to discover all other moleculer nodes. It's quick and fast but if you have too many nodes (>100), the nodes can generate a lot of heartbeat packets which can reduce the performance of request/response packets.
**Example**
```js
// moleculer.config.js
module.exports = {
registry: {
discoverer: "Local"
}
}
```
**Example with options**
```js
// moleculer.config.js
module.exports = {
registry: {
discoverer: {
type: "Local",
options: {
// Send heartbeat in every 10 seconds
heartbeatInterval: 10,
// Heartbeat timeout in seconds
heartbeatTimeout: 30,
// Disable heartbeat checking & sending, if true
disableHeartbeatChecks: false,
// Disable removing offline nodes from registry, if true
disableOfflineNodeRemoving: false,
// Remove offline nodes after 10 minutes
cleanOfflineNodesTimeout: 10 * 60
}
}
}
}
```
### Redis Discoverer
>**This is an experimental module. Do not use it in production yet!**
This Discoverer uses a [Redis server](https://redis.io/) to discover Moleculer nodes. The heartbeat & discovery packets are stored in Redis keys. Thanks to Redis key expiration, if a node crashed or disconnected unexpectedly, the Redis will remove its heartbeat keys from the server and other nodes can detect it.
**Example to connect local Redis server**
```js
// moleculer.config.js
module.exports = {
registry: {
discoverer: "Redis"
}
}
```
**Example to connect remote Redis server**
```js
// moleculer.config.js
module.exports = {
registry: {
discoverer: "redis://redis-server:6379"
}
}
```
**Example with options**
```js
// moleculer.config.js
module.exports = {
registry: {
discoverer: {
type: "Redis",
options: {
redis: {
// Redis connection options.
// More info: https://github.com/luin/ioredis#connect-to-redis
port: 6379,
host: "redis-server",
password: "123456",
db: 3
}
// Serializer
serializer: "JSON",
// Full heartbeat checks. It generates more network traffic
// 10 means every 10 cycle.
fullCheck: 10,
// Key scanning size
scanLength: 100,
// Monitoring Redis commands
monitor: true,
// --- COMMON DISCOVERER OPTIONS ---
// Send heartbeat in every 10 seconds
heartbeatInterval: 10,
// Heartbeat timeout in seconds
heartbeatTimeout: 30,
// Disable heartbeat checking & sending, if true
disableHeartbeatChecks: false,
// Disable removing offline nodes from registry, if true
disableOfflineNodeRemoving: false,
// Remove offline nodes after 10 minutes
cleanOfflineNodesTimeout: 10 * 60
}
}
}
}
```
>To be able to use this Discoverer, install the `ioredis` module with the npm install ioredis --save command.
>Tip: To further network traffic reduction, you can use MsgPack/Notepack serializers instead of JSON.
### Etcd3 Discoverer
>This is an experimental module. Do not use it in production yet!
This Discoverer uses an [etcd3 server](https://etcd.io/) to discover Moleculer nodes. The heartbeat & discovery packets are stored in the server. Thanks to etcd3 [lease](https://etcd.io/docs/v3.4.0/learning/api/#lease-api) solution, if a node crashed or disconnected unexpectedly, the etcd3 will remove its heartbeat keys from the server and other nodes can detect it.
**Example to connect local etcd3 server**
```js
// moleculer.config.js
module.exports = {
registry: {
discoverer: "Etcd3"
}
}
```
**Example to connect remote etcd3 server**
```js
// moleculer.config.js
module.exports = {
registry: {
discoverer: "etcd3://etcd-server:2379"
}
}
```
**Example with options**
```js
// moleculer.config.js
module.exports = {
registry: {
discoverer: {
type: "Etcd3",
options: {
etcd: {
// etcd3 connection options.
// More info: https://mixer.github.io/etcd3/interfaces/options_.ioptions.html
hosts: "etcd-server:2379",
auth: "12345678"
}
// Serializer
serializer: "JSON",
// Full heartbeat checks. It generates more network traffic
// 10 means every 10 cycle.
fullCheck: 10,
// --- COMMON DISCOVERER OPTIONS ---
// Send heartbeat in every 10 seconds
heartbeatInterval: 10,
// Heartbeat timeout in seconds
heartbeatTimeout: 30,
// Disable heartbeat checking & sending, if true
disableHeartbeatChecks: false,
// Disable removing offline nodes from registry, if true
disableOfflineNodeRemoving: false,
// Remove offline nodes after 10 minutes
cleanOfflineNodesTimeout: 10 * 60
}
}
}
}
```
>To be able to use this Discoverer, install the `etcd3` module with the npm install etcd3--save command.
>Tip: To further network traffic reduction, you can use MsgPack/Notepack serializers instead of JSON.
### Custom Discoverer
You can create your custom Discoverer. We recommend to copy the source of Redis Discoverer and implement the necessary methods.
## Other changes
- fixed multiple heartbeat sending issue at transporter reconnecting.
- the `heartbeatInterval` default value has been changed to `10` seconds.
- the `heartbeatTimeout` default value has been changed to `30` seconds.
- the heartbeat check logics use process uptime instead of timestamps in order to avoid issues with time synchronization or daylight saving.
- Notepack serializer initialization issue fixed. It caused problem when Redis cacher uses Notepack serializer.
- new `removeFromArray` function in Utils.
- `mcall` method definition fixed in Typescript definition.
- dependencies updated.