aedes 0.51.3 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/.claude/settings.local.json +12 -0
  2. package/.github/actions/sticky-pr-comment/action.yml +55 -0
  3. package/.github/workflows/benchmark-compare-serial.yml +60 -0
  4. package/.github/workflows/ci.yml +12 -17
  5. package/.release-it.json +18 -0
  6. package/.taprc +15 -6
  7. package/README.md +6 -4
  8. package/aedes.d.ts +0 -6
  9. package/aedes.js +270 -242
  10. package/benchmarks/README.md +33 -0
  11. package/benchmarks/pingpong.js +94 -25
  12. package/benchmarks/receiver.js +77 -0
  13. package/benchmarks/report.js +150 -0
  14. package/benchmarks/runBenchmarks.js +118 -0
  15. package/benchmarks/sender.js +86 -0
  16. package/benchmarks/server.js +19 -18
  17. package/checkVersion.js +20 -0
  18. package/docs/Aedes.md +66 -8
  19. package/docs/Client.md +3 -4
  20. package/docs/Examples.md +39 -22
  21. package/docs/MIGRATION.md +50 -0
  22. package/eslint.config.js +8 -0
  23. package/example.js +51 -40
  24. package/examples/clusters/index.js +28 -23
  25. package/examples/clusters/package.json +10 -6
  26. package/lib/client.js +405 -306
  27. package/lib/handlers/connect.js +42 -38
  28. package/lib/handlers/index.js +9 -11
  29. package/lib/handlers/ping.js +2 -3
  30. package/lib/handlers/puback.js +5 -5
  31. package/lib/handlers/publish.js +29 -14
  32. package/lib/handlers/pubrec.js +9 -17
  33. package/lib/handlers/pubrel.js +34 -25
  34. package/lib/handlers/subscribe.js +47 -43
  35. package/lib/handlers/unsubscribe.js +16 -19
  36. package/lib/qos-packet.js +14 -17
  37. package/lib/utils.js +5 -12
  38. package/lib/write.js +4 -5
  39. package/package.json +139 -136
  40. package/test/auth.js +468 -804
  41. package/test/basic.js +613 -575
  42. package/test/bridge.js +44 -40
  43. package/test/client-pub-sub.js +531 -504
  44. package/test/close_socket_by_other_party.js +137 -102
  45. package/test/connect.js +487 -484
  46. package/test/drain-timeout.js +593 -0
  47. package/test/drain-toxiproxy.js +620 -0
  48. package/test/events.js +173 -145
  49. package/test/helper.js +351 -73
  50. package/test/keep-alive.js +40 -67
  51. package/test/meta.js +257 -210
  52. package/test/not-blocking.js +93 -197
  53. package/test/qos1.js +464 -554
  54. package/test/qos2.js +308 -393
  55. package/test/regr-21.js +39 -21
  56. package/test/require.cjs +22 -0
  57. package/test/retain.js +349 -398
  58. package/test/topics.js +176 -183
  59. package/test/types/aedes.test-d.ts +4 -8
  60. package/test/will.js +310 -428
  61. package/types/instance.d.ts +40 -35
  62. package/types/packet.d.ts +10 -10
  63. package/.coveralls.yml +0 -1
  64. package/benchmarks/bombing.js +0 -34
  65. package/benchmarks/bombingQoS1.js +0 -36
  66. package/benchmarks/throughputCounter.js +0 -23
  67. package/benchmarks/throughputCounterQoS1.js +0 -33
  68. package/types/.eslintrc.json +0 -47
package/aedes.js CHANGED
@@ -1,24 +1,21 @@
1
- 'use strict'
2
-
3
- const EventEmitter = require('events')
4
- const util = require('util')
5
- const parallel = require('fastparallel')
6
- const series = require('fastseries')
7
- const { v4: uuidv4 } = require('uuid')
8
- const reusify = require('reusify')
9
- const { pipeline } = require('stream')
10
- const Packet = require('aedes-packet')
11
- const memory = require('aedes-persistence')
12
- const mqemitter = require('mqemitter')
13
- const Client = require('./lib/client')
14
- const { $SYS_PREFIX, bulk } = require('./lib/utils')
15
-
16
- module.exports = Aedes.createBroker = Aedes
1
+ import EventEmitter from 'node:events'
2
+ import parallel from 'fastparallel'
3
+ import series from 'fastseries'
4
+ import { v4 as uuidv4 } from 'uuid'
5
+ import reusify from 'reusify'
6
+ import { pipeline } from 'stream'
7
+ import Packet from 'aedes-packet'
8
+ import memory from 'aedes-persistence'
9
+ import mqemitter from 'mqemitter'
10
+ import Client from './lib/client.js'
11
+ import { $SYS_PREFIX, bulk } from './lib/utils.js'
12
+ import pkg from './package.json' with { type: 'json' }
17
13
 
18
14
  const defaultOptions = {
19
15
  concurrency: 100,
20
16
  heartbeatInterval: 60000, // 1 minute
21
17
  connectTimeout: 30000, // 30 secs
18
+ drainTimeout: 60000, // 60 secs - protects against slow/frozen clients by default, set to 0 to disable
22
19
  decodeProtocol: null,
23
20
  preConnect: defaultPreConnect,
24
21
  authenticate: defaultAuthenticate,
@@ -32,166 +29,255 @@ const defaultOptions = {
32
29
  maxClientsIdLength: 23,
33
30
  keepaliveLimit: 0
34
31
  }
32
+ const version = pkg.version
33
+
34
+ export class Aedes extends EventEmitter {
35
+ constructor (opts) {
36
+ super()
37
+ const that = this
38
+
39
+ opts = Object.assign({}, defaultOptions, opts)
40
+ this.opts = opts
41
+ this.id = opts.id || uuidv4()
42
+ // +1 when construct a new aedes-packet
43
+ // internal track for last brokerCounter
44
+ this.counter = 0
45
+ this.queueLimit = opts.queueLimit
46
+ this.connectTimeout = opts.connectTimeout
47
+ this.keepaliveLimit = opts.keepaliveLimit
48
+ this.maxClientsIdLength = opts.maxClientsIdLength
49
+ this.mq = opts.mq || mqemitter({
50
+ concurrency: opts.concurrency,
51
+ matchEmptyLevels: true // [MQTT-4.7.1-3]
52
+ })
53
+ this.handle = function handle (conn, req) {
54
+ conn.setMaxListeners(opts.concurrency * 2)
55
+ // create a new Client instance for a new connection
56
+ // return, just to please standard
57
+ return new Client(that, conn, req)
58
+ }
35
59
 
36
- function Aedes (opts) {
37
- const that = this
60
+ this._parallel = parallel()
61
+ this._series = series()
62
+ this._enqueuers = reusify(DoEnqueues)
38
63
 
39
- if (!(this instanceof Aedes)) {
40
- return new Aedes(opts)
41
- }
64
+ this.preConnect = opts.preConnect
65
+ this.authenticate = opts.authenticate
66
+ this.authorizePublish = opts.authorizePublish
67
+ this.authorizeSubscribe = opts.authorizeSubscribe
68
+ this.authorizeForward = opts.authorizeForward
69
+ this.published = opts.published
42
70
 
43
- opts = Object.assign({}, defaultOptions, opts)
44
-
45
- this.id = opts.id || uuidv4()
46
- // +1 when construct a new aedes-packet
47
- // internal track for last brokerCounter
48
- this.counter = 0
49
- this.queueLimit = opts.queueLimit
50
- this.connectTimeout = opts.connectTimeout
51
- this.keepaliveLimit = opts.keepaliveLimit
52
- this.maxClientsIdLength = opts.maxClientsIdLength
53
- this.mq = opts.mq || mqemitter({
54
- concurrency: opts.concurrency,
55
- matchEmptyLevels: true // [MQTT-4.7.1-3]
56
- })
57
- this.handle = function handle (conn, req) {
58
- conn.setMaxListeners(opts.concurrency * 2)
59
- // create a new Client instance for a new connection
60
- // return, just to please standard
61
- return new Client(that, conn, req)
62
- }
63
- this.persistence = opts.persistence || memory()
64
- this.persistence.broker = this
65
- this._parallel = parallel()
66
- this._series = series()
67
- this._enqueuers = reusify(DoEnqueues)
71
+ this.decodeProtocol = opts.decodeProtocol
72
+ this.trustProxy = opts.trustProxy
73
+ this.trustedProxies = opts.trustedProxies
68
74
 
69
- this.preConnect = opts.preConnect
70
- this.authenticate = opts.authenticate
71
- this.authorizePublish = opts.authorizePublish
72
- this.authorizeSubscribe = opts.authorizeSubscribe
73
- this.authorizeForward = opts.authorizeForward
74
- this.published = opts.published
75
+ this.clients = {}
76
+ this.brokers = {}
77
+ this.closed = true
78
+ }
75
79
 
76
- this.decodeProtocol = opts.decodeProtocol
77
- this.trustProxy = opts.trustProxy
78
- this.trustedProxies = opts.trustedProxies
80
+ async listen () {
81
+ const opts = this.opts
82
+ const that = this
79
83
 
80
- this.clients = {}
81
- this.brokers = {}
84
+ // metadata
85
+ this.connectedClients = 0
86
+ this.closed = false
82
87
 
83
- const heartbeatTopic = $SYS_PREFIX + that.id + '/heartbeat'
84
- const birthTopic = $SYS_PREFIX + that.id + '/birth'
88
+ this.persistence = opts.persistence || memory()
89
+ if (this.persistence.setup.constructor.name !== 'AsyncFunction') {
90
+ throw new Error('persistence.setup() must be an async function')
91
+ }
92
+ await this.persistence.setup(this)
85
93
 
86
- this._heartbeatInterval = setInterval(heartbeat, opts.heartbeatInterval)
94
+ const heartbeatTopic = $SYS_PREFIX + that.id + '/heartbeat'
95
+ const birthTopic = $SYS_PREFIX + that.id + '/birth'
87
96
 
88
- const bufId = Buffer.from(that.id, 'utf8')
97
+ this._heartbeatInterval = setInterval(heartbeat, opts.heartbeatInterval)
89
98
 
90
- // in a cluster env this is used to warn other broker instances
91
- // that this broker is alive
92
- that.publish({
93
- topic: birthTopic,
94
- payload: bufId
95
- }, noop)
99
+ const bufId = Buffer.from(that.id, 'utf8')
96
100
 
97
- function heartbeat () {
101
+ // in a cluster env this is used to warn other broker instances
102
+ // that this broker is alive
98
103
  that.publish({
99
- topic: heartbeatTopic,
104
+ topic: birthTopic,
100
105
  payload: bufId
101
106
  }, noop)
102
- }
103
107
 
104
- function deleteOldBrokers (broker) {
105
- if (that.brokers[broker] + (3 * opts.heartbeatInterval) < Date.now()) {
106
- delete that.brokers[broker]
108
+ function heartbeat () {
109
+ that.publish({
110
+ topic: heartbeatTopic,
111
+ payload: bufId
112
+ }, noop)
113
+ }
114
+
115
+ function deleteOldBrokers (broker) {
116
+ if (that.brokers[broker] + (3 * opts.heartbeatInterval) < Date.now()) {
117
+ delete that.brokers[broker]
118
+ }
107
119
  }
108
- }
109
120
 
110
- this._clearWillInterval = setInterval(function () {
111
- Object.keys(that.brokers).forEach(deleteOldBrokers)
121
+ this._clearWillInterval = setInterval(function () {
122
+ Object.keys(that.brokers).forEach(deleteOldBrokers)
112
123
 
113
- pipeline(
114
- that.persistence.streamWill(that.brokers),
115
- bulk(receiveWills),
116
- function done (err) {
117
- if (err) {
118
- that.emit('error', err)
124
+ pipeline(
125
+ that.persistence.streamWill(that.brokers),
126
+ bulk(receiveWills),
127
+ function done (err) {
128
+ if (err) {
129
+ that.emit('error', err)
130
+ }
119
131
  }
120
- }
121
- )
122
- }, opts.heartbeatInterval * 4)
132
+ )
133
+ }, opts.heartbeatInterval * 4)
123
134
 
124
- function receiveWills (chunks, done) {
125
- that._parallel(that, checkAndPublish, chunks, done)
126
- }
135
+ function receiveWills (chunks, done) {
136
+ that._parallel(that, checkAndPublish, chunks, done)
137
+ }
138
+
139
+ function checkAndPublish (will, done) {
140
+ const notPublish = that.brokers[will.brokerId] !== undefined && that.brokers[will.brokerId] + (3 * opts.heartbeatInterval) >= Date.now()
127
141
 
128
- function checkAndPublish (will, done) {
129
- const notPublish =
130
- that.brokers[will.brokerId] !== undefined && that.brokers[will.brokerId] + (3 * opts.heartbeatInterval) >= Date.now()
142
+ if (notPublish) return done()
131
143
 
132
- if (notPublish) return done()
144
+ // randomize this, so that multiple brokers
145
+ // do not publish the same wills at the same time
146
+ this.authorizePublish(that.clients[will.clientId] || null, will, function (err) {
147
+ if (err) { return doneWill() }
148
+ that.publish(will, doneWill)
133
149
 
134
- // randomize this, so that multiple brokers
135
- // do not publish the same wills at the same time
136
- this.authorizePublish(that.clients[will.clientId] || null, will, function (err) {
137
- if (err) { return doneWill() }
138
- that.publish(will, doneWill)
150
+ function doneWill (err) {
151
+ if (err) { return done(err) }
152
+ that.persistence.delWill({
153
+ id: will.clientId,
154
+ brokerId: will.brokerId
155
+ }).then(will => done(undefined, will), done)
156
+ }
157
+ })
158
+ }
139
159
 
140
- function doneWill (err) {
141
- if (err) { return done(err) }
142
- that.persistence.delWill({
143
- id: will.clientId,
144
- brokerId: will.brokerId
145
- }, done)
160
+ this.mq.on($SYS_PREFIX + '+/heartbeat', function storeBroker (packet, done) {
161
+ that.brokers[packet.payload.toString()] = Date.now()
162
+ done()
163
+ })
164
+
165
+ this.mq.on($SYS_PREFIX + '+/birth', function brokerBorn (packet, done) {
166
+ const brokerId = packet.payload.toString()
167
+
168
+ // reset duplicates counter
169
+ if (brokerId !== that.id) {
170
+ for (const clientId in that.clients) {
171
+ delete that.clients[clientId].duplicates[brokerId]
172
+ }
173
+ }
174
+
175
+ done()
176
+ })
177
+
178
+ this.mq.on($SYS_PREFIX + '+/new/clients', function closeSameClients (packet, done) {
179
+ const serverId = packet.topic.split('/')[1]
180
+ const clientId = packet.payload.toString()
181
+
182
+ if (that.clients[clientId] && serverId !== that.id) {
183
+ if (that.clients[clientId].closed) {
184
+ // remove the client from the list if it is already closed
185
+ that.deleteClient(clientId)
186
+ done()
187
+ } else {
188
+ that.clients[clientId].close(done)
189
+ }
190
+ } else {
191
+ done()
146
192
  }
147
193
  })
148
194
  }
149
195
 
150
- this.mq.on($SYS_PREFIX + '+/heartbeat', function storeBroker (packet, done) {
151
- that.brokers[packet.payload.toString()] = Date.now()
152
- done()
153
- })
196
+ get version () {
197
+ return version
198
+ }
154
199
 
155
- this.mq.on($SYS_PREFIX + '+/birth', function brokerBorn (packet, done) {
156
- const brokerId = packet.payload.toString()
200
+ static async createBroker (opts) {
201
+ const aedes = new Aedes(opts)
202
+ await aedes.listen()
203
+ return aedes
204
+ }
157
205
 
158
- // reset duplicates counter
159
- if (brokerId !== that.id) {
160
- for (const clientId in that.clients) {
161
- delete that.clients[clientId].duplicates[brokerId]
162
- }
206
+ publish (packet, client, done) {
207
+ if (typeof client === 'function') {
208
+ done = client
209
+ client = null
163
210
  }
211
+ const p = new Packet(packet, this)
212
+ const publishFuncs = p.qos > 0 ? publishFuncsQoS : publishFuncsSimple
164
213
 
165
- done()
166
- })
214
+ this._series(new PublishState(this, client, packet), publishFuncs, p, done)
215
+ }
167
216
 
168
- this.mq.on($SYS_PREFIX + '+/new/clients', function closeSameClients (packet, done) {
169
- const serverId = packet.topic.split('/')[1]
170
- const clientId = packet.payload.toString()
217
+ subscribe (topic, func, done) {
218
+ this.mq.on(topic, func, done)
219
+ }
171
220
 
172
- if (that.clients[clientId] && serverId !== that.id) {
173
- if (that.clients[clientId].closed) {
174
- // remove the client from the list if it is already closed
175
- that.deleteClient(clientId)
176
- done()
177
- } else {
178
- that.clients[clientId].close(done)
179
- }
221
+ unsubscribe (topic, func, done) {
222
+ this.mq.removeListener(topic, func, done)
223
+ }
224
+
225
+ registerClient (client) {
226
+ const that = this
227
+ if (this.clients[client.id]) {
228
+ // [MQTT-3.1.4-2]
229
+ this.clients[client.id].close(function closeClient () {
230
+ that._finishRegisterClient(client)
231
+ })
180
232
  } else {
181
- done()
233
+ this._finishRegisterClient(client)
182
234
  }
183
- })
235
+ }
184
236
 
185
- // metadata
186
- this.connectedClients = 0
187
- this.closed = false
188
- }
237
+ _finishRegisterClient (client) {
238
+ this.connectedClients++
239
+ this.clients[client.id] = client
240
+ this.emit('client', client)
241
+ this.publish({
242
+ topic: $SYS_PREFIX + this.id + '/new/clients',
243
+ payload: Buffer.from(client.id, 'utf8')
244
+ }, noop)
245
+ }
246
+
247
+ unregisterClient (client) {
248
+ this.deleteClient(client.id)
249
+ this.emit('clientDisconnect', client)
250
+ this.publish({
251
+ topic: $SYS_PREFIX + this.id + '/disconnect/clients',
252
+ payload: Buffer.from(client.id, 'utf8')
253
+ }, noop)
254
+ }
189
255
 
190
- util.inherits(Aedes, EventEmitter)
256
+ deleteClient (clientId) {
257
+ this.connectedClients--
258
+ delete this.clients[clientId]
259
+ }
260
+
261
+ close (cb = noop) {
262
+ const that = this
263
+ if (this.closed) {
264
+ return cb()
265
+ }
266
+ this.closed = true
267
+ clearInterval(this._heartbeatInterval)
268
+ clearInterval(this._clearWillInterval)
269
+ this._parallel(this, closeClient, Object.keys(this.clients), doneClose)
270
+ function doneClose () {
271
+ that.emit('closed')
272
+ that.mq.close(cb)
273
+ }
274
+ }
275
+ }
191
276
 
192
277
  function storeRetained (packet, done) {
193
278
  if (packet.retain) {
194
- this.broker.persistence.storeRetained(packet, done)
279
+ this.broker.persistence.storeRetained(packet)
280
+ .then(() => done(null), done)
195
281
  } else {
196
282
  done()
197
283
  }
@@ -209,45 +295,46 @@ function enqueueOffline (packet, done) {
209
295
  enqueuer.packet = packet
210
296
  enqueuer.topic = packet.topic
211
297
  enqueuer.broker = this.broker
212
- this.broker.persistence.subscriptionsByTopic(
213
- packet.topic,
214
- enqueuer.done
215
- )
298
+ this.broker.persistence.subscriptionsByTopic(packet.topic)
299
+ .then(subs => enqueuer.done(null, subs), enqueuer.done)
216
300
  }
217
301
 
218
- function DoEnqueues () {
219
- this.next = null
220
- this.complete = null
221
- this.packet = null
222
- this.topic = null
223
- this.broker = null
302
+ class DoEnqueues {
303
+ constructor () {
304
+ this.next = null
305
+ this.complete = null
306
+ this.packet = null
307
+ this.topic = null
308
+ this.broker = null
309
+
310
+ const that = this
311
+
312
+ this.done = function doneEnqueue (err, subs) {
313
+ const broker = that.broker
314
+
315
+ if (err) {
316
+ // is this really recoverable?
317
+ // let's just error the whole aedes
318
+ // https://nodejs.org/api/events.html#events_error_events
319
+ broker.emit('error', err)
320
+ return
321
+ }
224
322
 
225
- const that = this
323
+ if (that.topic.indexOf($SYS_PREFIX) === 0) {
324
+ subs = subs.filter(removeSharp)
325
+ }
226
326
 
227
- this.done = function doneEnqueue (err, subs) {
228
- const broker = that.broker
327
+ const packet = that.packet
328
+ const complete = that.complete
229
329
 
230
- if (err) {
231
- // is this really recoverable?
232
- // let's just error the whole aedes
233
- // https://nodejs.org/api/events.html#events_error_events
234
- broker.emit('error', err)
235
- return
236
- }
330
+ that.packet = null
331
+ that.complete = null
332
+ that.topic = null
237
333
 
238
- if (that.topic.indexOf($SYS_PREFIX) === 0) {
239
- subs = subs.filter(removeSharp)
334
+ broker.persistence.outgoingEnqueueCombi(subs, packet)
335
+ .then(() => complete(null), complete)
336
+ broker._enqueuers.release(that)
240
337
  }
241
-
242
- const packet = that.packet
243
- const complete = that.complete
244
-
245
- that.packet = null
246
- that.complete = null
247
- that.topic = null
248
-
249
- broker.persistence.outgoingEnqueueCombi(subs, packet, complete)
250
- broker._enqueuers.release(that)
251
338
  }
252
339
  }
253
340
 
@@ -274,82 +361,11 @@ const publishFuncsQoS = [
274
361
  emitPacket,
275
362
  callPublished
276
363
  ]
277
- Aedes.prototype.publish = function (packet, client, done) {
278
- if (typeof client === 'function') {
279
- done = client
280
- client = null
281
- }
282
- const p = new Packet(packet, this)
283
- const publishFuncs = p.qos > 0 ? publishFuncsQoS : publishFuncsSimple
284
-
285
- this._series(new PublishState(this, client, packet), publishFuncs, p, done)
286
- }
287
-
288
- Aedes.prototype.subscribe = function (topic, func, done) {
289
- this.mq.on(topic, func, done)
290
- }
291
-
292
- Aedes.prototype.unsubscribe = function (topic, func, done) {
293
- this.mq.removeListener(topic, func, done)
294
- }
295
-
296
- Aedes.prototype.registerClient = function (client) {
297
- const that = this
298
- if (this.clients[client.id]) {
299
- // [MQTT-3.1.4-2]
300
- this.clients[client.id].close(function closeClient () {
301
- that._finishRegisterClient(client)
302
- })
303
- } else {
304
- this._finishRegisterClient(client)
305
- }
306
- }
307
-
308
- Aedes.prototype._finishRegisterClient = function (client) {
309
- this.connectedClients++
310
- this.clients[client.id] = client
311
- this.emit('client', client)
312
- this.publish({
313
- topic: $SYS_PREFIX + this.id + '/new/clients',
314
- payload: Buffer.from(client.id, 'utf8')
315
- }, noop)
316
- }
317
-
318
- Aedes.prototype.unregisterClient = function (client) {
319
- this.deleteClient(client.id)
320
- this.emit('clientDisconnect', client)
321
- this.publish({
322
- topic: $SYS_PREFIX + this.id + '/disconnect/clients',
323
- payload: Buffer.from(client.id, 'utf8')
324
- }, noop)
325
- }
326
-
327
- Aedes.prototype.deleteClient = function (clientId) {
328
- this.connectedClients--
329
- delete this.clients[clientId]
330
- }
331
364
 
332
365
  function closeClient (client, cb) {
333
366
  this.clients[client].close(cb)
334
367
  }
335
368
 
336
- Aedes.prototype.close = function (cb = noop) {
337
- const that = this
338
- if (this.closed) {
339
- return cb()
340
- }
341
- this.closed = true
342
- clearInterval(this._heartbeatInterval)
343
- clearInterval(this._clearWillInterval)
344
- this._parallel(this, closeClient, Object.keys(this.clients), doneClose)
345
- function doneClose () {
346
- that.emit('closed')
347
- that.mq.close(cb)
348
- }
349
- }
350
-
351
- Aedes.prototype.version = require('./package.json').version
352
-
353
369
  function defaultPreConnect (client, packet, callback) {
354
370
  callback(null, true)
355
371
  }
@@ -377,10 +393,22 @@ function defaultPublished (packet, client, callback) {
377
393
  callback(null)
378
394
  }
379
395
 
380
- function PublishState (broker, client, packet) {
381
- this.broker = broker
382
- this.client = client
383
- this.packet = packet
396
+ class PublishState {
397
+ constructor (broker, client, packet) {
398
+ this.broker = broker
399
+ this.client = client
400
+ this.packet = packet
401
+ }
384
402
  }
385
403
 
386
404
  function noop () {}
405
+
406
+ function warnMigrate () {
407
+ throw new Error(
408
+ ` Aedes default export has been removed.
409
+ Use 'const aedes = await Aedes.createBroker()' instead.
410
+ See: https://github.com/moscajs/aedes/docs/MIGRATION.MD
411
+ `)
412
+ }
413
+
414
+ export default warnMigrate
@@ -0,0 +1,33 @@
1
+ # Benchmarks
2
+
3
+ This folder contains a number of scripts to perform benchmark testing and
4
+ reporting on it:
5
+
6
+ - sender.js publishes messages with a serialnumber as payload (add '-q 1' to get QoS1)
7
+ - receiver.js subscribes and validates the serialnumber (add '-q 1' to get QoS1)
8
+ - pingpong.js measures latency between sending and receiving the same
9
+ message
10
+ - server.js starts the Aedes server to use in the test
11
+ - runBenchmarks.js starts the server and runs Publish/Subscribe tests
12
+ with QoS0 and QoS1 using the scripts above it produces CSV data, this
13
+ data includes the current git branch name.
14
+ - report.js reads the CSV data from STDIN and turns it into a Markdown
15
+ report.
16
+
17
+ Examples:
18
+
19
+ ```bash
20
+ node runBenchmark.js > result.csv
21
+ cat result.csv | node report.csv > result.md
22
+ ```
23
+
24
+ ```bash
25
+ node runBenchmark.js > result.branch.csv
26
+ cat result.main.csv result.branch.csv | node report.csv > result.combined.md
27
+ ```
28
+
29
+ ## WARNING
30
+
31
+ Running benchmarks and especially interpreting results can be misleading
32
+ E.g. performance of the benchmark run might depend on the presence (or absence)
33
+ of other, unrelated, activity in the system.