Skip to content

Commit 41f70a8

Browse files
committed
changelog & migration guide
1 parent 22e4fc2 commit 41f70a8

File tree

2 files changed

+336
-182
lines changed

2 files changed

+336
-182
lines changed

CHANGELOG.md

+310
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,313 @@
1+
<a name="0.15.0"></a>
2+
# [0.15.0](https://github.com/moleculerjs/moleculer/compare/v0.14.29...v0.15.0) (2023-xx-xx)
3+
4+
[**Migration guide from 0.14 to 0.15**](https://github.com/moleculerjs/moleculer/blob/next/docs/MIGRATION_GUIDE_0.15.md)
5+
6+
# Breaking changes
7+
8+
## Minimum Node 18
9+
The minimum supported Node version is changed from Node 10 to Node 18.
10+
11+
## Communication protocol has been changed
12+
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.
13+
14+
## Schema-based serializers (ProtoBuf, Avro, Thrift) are removed
15+
16+
The reason is desribed in this issue: https://github.com/moleculerjs/moleculer/issues/882
17+
18+
If you use one of those, you should change it to one of these schemaless serializers: MsgPack, Notepack.io, JSON, JSONExt, CBOR
19+
20+
## Action streaming
21+
22+
The built-in `Stream` sending has been rewritten. Now it accepts `params` besides the `Stream` instance.
23+
The `Stream` parameter moved from `ctx.params` into calling options under a `stream` property.
24+
25+
### New way to send a stream with extra parameters
26+
The stream instance is passed as a calling options, so you can use `ctx.params` as a normal action call.
27+
28+
```js
29+
ctx.call("file.save", { filename: "as.txt" }, { stream: fs.createReadStream() });
30+
```
31+
32+
### New way to receive a stream
33+
34+
```js
35+
// file.service.js
36+
module.exports = {
37+
name: "file",
38+
actions: {
39+
save(ctx) {
40+
// The stream is in Context directly
41+
const stream = ctx.stream;
42+
const s = fs.createWriteStream(ctx.params.filename);
43+
stream.pipe(s);
44+
}
45+
}
46+
};
47+
```
48+
49+
## Removed deprecated functions and signatures
50+
51+
### Removed deprecated event sending method signature
52+
53+
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`.
54+
This signature is removed, you should always pass an `opts` object as 3rd argument.
55+
56+
### Removed deprecated middleware as a `Function`
57+
We removed and old and deprecated middleware signature where the middleware was `localAction` function. Now `ServiceBroker` accepts middleware as `Object` only.
58+
59+
### Removed deprecated `getLocalService` signature.
60+
61+
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}`
62+
63+
### Removed `Service` constructor 3rd argument.
64+
65+
The `Service` constructor had a 3rd argument as `schemaMods` which was deprecated because you should use `mixins` instead modifier schemas.
66+
67+
## Garbage collector and event-loop metrics removed
68+
69+
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.
70+
71+
**Removed metrics:**
72+
- `process.gc.time`
73+
- `process.gc.total.time`
74+
- `process.gc.executed.total`
75+
- `process.eventloop.lag.min`
76+
- `process.eventloop.lag.avg`
77+
- `process.eventloop.lag.max`
78+
- `process.eventloop.lag.count`
79+
80+
## Removed STAN (NATS Streaming) transporter
81+
82+
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
83+
84+
## Rewritten Kafka transporter (based on kafkajs)
85+
86+
The previous `kafka-node` based transporter has been rewritten to a `kafkajs` based transporter. It means, you should migrate your Kafka Transporter options.
87+
88+
```js
89+
// moleculer.config.js
90+
module.exports = {
91+
transporter: {
92+
type: "Kafka",
93+
options: {
94+
// KafkaClient options. More info: https://kafka.js.org/docs/configuration
95+
client: {
96+
brokers: [/*...*/]
97+
},
98+
99+
// KafkaProducer options. More info: https://kafka.js.org/docs/producing#options
100+
producer: {},
101+
102+
// ConsumerGroup options. More info: https://kafka.js.org/docs/consuming#a-name-options-a-options
103+
consumer: {},
104+
105+
// Advanced options for `send`. More info: https://kafka.js.org/docs/producing#producing-messages
106+
publish: {},
107+
108+
// Advanced message options for `send`. More info: https://kafka.js.org/docs/producing#message-structure
109+
publishMessage: {
110+
partition: 0
111+
}
112+
}
113+
}
114+
}
115+
```
116+
117+
About new configuration options, check this documentation: https://kafka.js.org/docs/configuration
118+
119+
## Removed legacy NATS library ([email protected]) implementation
120+
121+
The legacy `[email protected]` transporter implementation is removed. This version supports only `[email protected]` library.
122+
123+
## The Fastest Validator options changed.
124+
125+
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.
126+
127+
You can see example about migration here: https://github.com/icebob/fastest-validator/blob/master/CHANGELOG.md#new-custom-function-signature
128+
129+
## Rewritten Typescript definition files
130+
131+
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.
132+
133+
134+
# New features
135+
136+
## New JSON Extended serializer
137+
138+
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.
139+
140+
### Example
141+
142+
```js
143+
// moleculer.config.js
144+
module.exports = {
145+
serializer: "JSONExt"
146+
}
147+
```
148+
149+
### Custom extensions
150+
151+
You can extend the serializer with custom types.
152+
153+
#### Example to extend with a custom class serializing/deserializing
154+
155+
```js
156+
// MyClass.js
157+
class MyClass {
158+
constructor(a, b) {
159+
this.a = a;
160+
this.b = b;
161+
}
162+
}
163+
```
164+
165+
```js
166+
// moleculer.config.js
167+
module.exports = {
168+
serializer: {
169+
type: "JSONExt",
170+
options: {
171+
customs: [
172+
{
173+
// This is the identifier of the custom type
174+
prefix: "AB",
175+
176+
// This function checks the type of JSON value
177+
check: v => v instanceof MyClass,
178+
179+
// Serialize the custom class properties to a String
180+
serialize: v => v.a + "|" + v.b,
181+
182+
// Deserialize the JSON string to custom class instance and set properties
183+
deserialize: v => {
184+
const [a, b] = v.split("|");
185+
return new MyClass(parseInt(a), b);
186+
}
187+
}
188+
]
189+
}
190+
}
191+
}
192+
```
193+
194+
## New Request headers
195+
196+
We added a new `headers` property in calling options and Context class to store meta information for an action calling or an event emitting.
197+
198+
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.
199+
200+
>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.
201+
202+
### Set headers in action calls
203+
204+
```js
205+
broker.call("posts.list", { limit: 100 }, {
206+
headers: {
207+
customProp: "customValue"
208+
}
209+
});
210+
```
211+
212+
> You can use the same way for event emitting or broadcasting.
213+
214+
### Read headers inside action handler
215+
216+
```js
217+
// posts.service.js
218+
module.exports = {
219+
name: "posts",
220+
actions: {
221+
list(ctx) {
222+
const customProp = ctx.headers.customProp;
223+
}
224+
}
225+
};
226+
```
227+
228+
> You can use the same way in event handlers.
229+
230+
### Use header value in cache keys
231+
232+
You can add headers values to the cache keys as well. For this, use `@` prefix
233+
234+
```js
235+
// posts.service.js
236+
module.exports = {
237+
name: "posts",
238+
actions: {
239+
list: {
240+
cache: {
241+
keys: [
242+
"limit", // value from `ctx.params`
243+
"#tenant", // value from `ctx.meta`
244+
"@customProp" // value from `ctx.headers`
245+
]
246+
}
247+
handler(ctx) {
248+
const customProp = ctx.headers.customProp;
249+
}
250+
}
251+
}
252+
};
253+
```
254+
### Response headers
255+
256+
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.
257+
258+
## Other changes
259+
260+
### Better error handling in event handlers.
261+
262+
!TODO!
263+
264+
### Cacher changes
265+
266+
#### The `getCacheKey` and `opts.keygen` signature has been changed
267+
268+
Old signature: `getCacheKey(actionName, params, meta, keys, actionKeygen)`
269+
270+
New signature: `getCacheKey(action, opts, ctx)`
271+
272+
273+
#### Added `missingResponse` option to cacher options
274+
275+
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`.
276+
277+
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.
278+
279+
**Example: using a custom symbol to detect missing entries**
280+
281+
```js
282+
const missingSymbol = Symbol("MISSING");
283+
284+
// moleculer.config.js
285+
module.exports = {
286+
cacher: {
287+
type: "Memory",
288+
options: {
289+
missingResponse: missingSymbol
290+
}
291+
}
292+
}
293+
294+
// Get data from cache
295+
296+
const res = await cacher.get("not-existing-key");
297+
if (res === cacher.opts.missingSymbol) {
298+
console.log("It's not cached.");
299+
}
300+
```
301+
302+
### Cache key generation changed
303+
304+
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`.
305+
In 0.15, string values are wrapped into quotes, the `null` is `null` and `undefined` is serialized as `undefined`, so similar serialized values.
306+
307+
These changes means the 0.15 cachers create different cache keys than 0.14 cachers.
308+
309+
310+
--------------------------------------------------
1311
<a name="Unreleased"></a>
2312
# [Unreleased](https://github.com/moleculerjs/moleculer/compare/v0.14.29...master)
3313

0 commit comments

Comments
 (0)