@weave-js/core 0.10.0 → 0.12.0

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 (132) hide show
  1. package/.eslintrc.js +1 -1
  2. package/jest.config.js +1 -1
  3. package/lib/ExtendableError.js +33 -0
  4. package/lib/broker/context.js +58 -46
  5. package/lib/broker/{default-options.js → defaultOptions.js} +31 -13
  6. package/lib/broker/index.js +273 -251
  7. package/lib/buildRuntime.js +70 -0
  8. package/lib/cache/adapters/base.js +119 -0
  9. package/lib/cache/adapters/inMemory.js +154 -0
  10. package/lib/cache/adapters/inMemoryLru.js +140 -0
  11. package/lib/cache/adapters/index.js +10 -0
  12. package/lib/cache/getCacheKeyByObject.js +31 -0
  13. package/lib/cache/getPropertyFromDataOrMetadata.js +20 -0
  14. package/lib/cache/lock.js +34 -11
  15. package/lib/constants.js +11 -8
  16. package/lib/{error-handler.js → errorHandler.js} +8 -8
  17. package/lib/errors.js +46 -39
  18. package/lib/helper/{define-action.js → defineAction.js} +5 -3
  19. package/lib/helper/{define-broker-options.js → defineBrokerOptions.js} +4 -2
  20. package/lib/helper/{define-service.js → defineService.js} +6 -3
  21. package/lib/index.js +25 -22
  22. package/lib/logger/base.js +38 -29
  23. package/lib/logger/format/asHumanReadable.js +15 -14
  24. package/lib/logger/format/asJson.js +10 -10
  25. package/lib/logger/format/index.js +3 -3
  26. package/lib/logger/index.js +28 -25
  27. package/lib/logger/levels.js +23 -22
  28. package/lib/logger/tools.js +17 -13
  29. package/lib/logger/utils/colorize.js +23 -23
  30. package/lib/logger/utils/format.js +89 -65
  31. package/lib/metrics/common.js +47 -47
  32. package/lib/metrics/constants.js +44 -44
  33. package/lib/metrics/exporter/base.js +8 -8
  34. package/lib/metrics/exporter/event.js +20 -20
  35. package/lib/metrics/exporter/index.js +15 -15
  36. package/lib/metrics/index.js +2 -2
  37. package/lib/metrics/types/base.js +20 -20
  38. package/lib/metrics/types/counter.js +6 -6
  39. package/lib/metrics/types/gauge.js +24 -24
  40. package/lib/metrics/types/histogram.js +26 -26
  41. package/lib/metrics/types/index.js +6 -6
  42. package/lib/metrics/types/info.js +17 -17
  43. package/lib/middlewares/action-hooks/index.js +82 -34
  44. package/lib/middlewares/bulkhead/index.js +34 -33
  45. package/lib/middlewares/cache/index.js +106 -0
  46. package/lib/middlewares/circuit-breaker/index.js +85 -60
  47. package/lib/middlewares/context-tracker/index.js +39 -39
  48. package/lib/middlewares/error-handler/index.js +14 -14
  49. package/lib/middlewares/index.js +3 -2
  50. package/lib/middlewares/metrics/getMiddlewareWrapper.js +17 -17
  51. package/lib/middlewares/metrics/index.js +29 -29
  52. package/lib/middlewares/retry/index.js +15 -15
  53. package/lib/middlewares/timeout/index.js +18 -18
  54. package/lib/middlewares/tracing/index.js +50 -37
  55. package/lib/middlewares/tracing/tags.js +43 -0
  56. package/lib/middlewares/validator/index.js +32 -32
  57. package/lib/registry/{action-endpoint.js → actionEndpoint.js} +8 -8
  58. package/lib/registry/collections/{action-collection.js → actionCollection.js} +39 -35
  59. package/lib/registry/collections/{endpoint-collection.js → endpointCollection.js} +64 -65
  60. package/lib/registry/collections/{event-collection.js → eventCollection.js} +65 -69
  61. package/lib/registry/collections/{node-collection.js → nodeCollection.js} +45 -45
  62. package/lib/registry/collections/{service-collection.js → serviceCollection.js} +61 -55
  63. package/lib/registry/eventEndpoint.js +26 -0
  64. package/lib/registry/load-balancer/base.js +3 -3
  65. package/lib/registry/load-balancer/index.js +7 -7
  66. package/lib/registry/node.js +27 -27
  67. package/lib/registry/registry.js +147 -163
  68. package/lib/registry/service/parseAction.js +16 -16
  69. package/lib/registry/service/parseEvent.js +18 -18
  70. package/lib/registry/service/reduceMixins.js +10 -10
  71. package/lib/registry/service/service.js +72 -72
  72. package/lib/registry/{service-item.js → serviceItem.js} +21 -21
  73. package/lib/runtime/{init-action-invoker.js → initActionInvoker.js} +21 -21
  74. package/lib/runtime/initCache.js +19 -0
  75. package/lib/runtime/{init-context-factory.js → initContextFactory.js} +22 -22
  76. package/lib/runtime/{init-eventbus.js → initEventbus.js} +54 -53
  77. package/lib/runtime/{init-logger.js → initLogger.js} +11 -11
  78. package/lib/runtime/{init-metrics.js → initMetrics.js} +55 -54
  79. package/lib/runtime/{init-middleware-manager.js → initMiddlewareManager.js} +21 -21
  80. package/lib/runtime/{init-registry.js → initRegistry.js} +6 -6
  81. package/lib/runtime/initServiceManager.js +145 -0
  82. package/lib/runtime/{init-tracing.js → initTracing.js} +25 -24
  83. package/lib/runtime/{init-transport.js → initTransport.js} +5 -5
  84. package/lib/runtime/{init-uuid-factory.js → initUuidFactory.js} +4 -4
  85. package/lib/runtime/{init-validator.js → initValidator.js} +5 -5
  86. package/lib/tracing/collectors/base.js +29 -37
  87. package/lib/tracing/collectors/event.js +33 -33
  88. package/lib/tracing/collectors/index.js +16 -16
  89. package/lib/tracing/span.js +34 -32
  90. package/lib/tracing/time.js +8 -8
  91. package/lib/transport/InboundTransformStream.js +75 -0
  92. package/lib/transport/adapters/adapteBase.js +107 -0
  93. package/lib/transport/adapters/adapters.js +4 -4
  94. package/lib/transport/adapters/dummy/index.js +19 -19
  95. package/lib/transport/adapters/fromURI.js +13 -13
  96. package/lib/transport/adapters/getAdapterByName.js +5 -5
  97. package/lib/transport/adapters/index.js +12 -12
  98. package/lib/transport/adapters/tcp/discovery/codec.js +4 -4
  99. package/lib/transport/adapters/tcp/discovery/index.js +90 -76
  100. package/lib/transport/adapters/tcp/index.js +180 -175
  101. package/lib/transport/adapters/tcp/tcp-messagetypes.js +7 -7
  102. package/lib/transport/adapters/tcp/tcpReader.js +39 -38
  103. package/lib/transport/adapters/tcp/tcpWriteStream.js +26 -26
  104. package/lib/transport/adapters/tcp/tcpWriter.js +58 -58
  105. package/lib/transport/adapters/tcp/utils.js +12 -12
  106. package/lib/transport/createMessage.js +11 -0
  107. package/lib/transport/createTransport.js +377 -334
  108. package/lib/transport/errorPayloadFactory.js +15 -0
  109. package/lib/transport/messageHandlers.js +517 -0
  110. package/lib/transport/messageTypes.js +23 -0
  111. package/lib/types.js +95 -71
  112. package/lib/utils/index.js +2 -2
  113. package/lib/utils/options.js +47 -45
  114. package/lib/utils/{restore-error.js → restoreError.js} +4 -4
  115. package/package.json +6 -12
  116. package/CHANGELOG.md +0 -1334
  117. package/lib/build-runtime.js +0 -70
  118. package/lib/cache/base.js +0 -142
  119. package/lib/cache/index.js +0 -48
  120. package/lib/cache/memory.js +0 -121
  121. package/lib/middlewares/tracing/buildTags.js +0 -17
  122. package/lib/new-errors.js +0 -25
  123. package/lib/registry/event-endpoint.js +0 -26
  124. package/lib/runtime/init-cache.js +0 -10
  125. package/lib/runtime/init-service-manager.js +0 -128
  126. package/lib/tracing/collectors/console.js +0 -34
  127. package/lib/tracing/index.js +0 -3
  128. package/lib/tracing/tracer.js +0 -64
  129. package/lib/transport/adapters/adapter-base.js +0 -92
  130. package/lib/transport/message-handlers.js +0 -448
  131. package/lib/transport/message-types.js +0 -59
  132. package/lib/transport/message.js +0 -16
@@ -1,16 +1,16 @@
1
- const loadTime = getNanoSeconds()
2
- const nodeLoadTime = loadTime - process.uptime() * 1e9
1
+ const loadTime = getNanoSeconds();
2
+ const nodeLoadTime = loadTime - process.uptime() * 1e9;
3
3
 
4
4
  function getNanoSeconds () {
5
- const time = process.hrtime()
6
- return time[0] * 1e9 + time[1]
5
+ const time = process.hrtime();
6
+ return time[0] * 1e9 + time[1];
7
7
  }
8
8
 
9
9
  function now () {
10
- return (getNanoSeconds() - nodeLoadTime) / 1e6
10
+ return (getNanoSeconds() - nodeLoadTime) / 1e6;
11
11
  }
12
12
 
13
- const loadNs = now()
14
- const loadMs = Date.now()
13
+ const loadNs = now();
14
+ const loadMs = Date.now();
15
15
 
16
- module.exports = () => loadMs + now() - loadNs
16
+ module.exports = () => loadMs + now() - loadNs;
@@ -0,0 +1,75 @@
1
+ const { Transform } = require('stream');
2
+
3
+ const pushWithBackpressure = (stream, chunks, encoding, callback = null, $index = 0) => {
4
+ if (!(stream instanceof Transform)) {
5
+ throw new TypeError('Argument "stream" must be an instance of Duplex');
6
+ }
7
+
8
+ chunks = [].concat(chunks).filter(x => x !== undefined);
9
+
10
+ if (typeof encoding === 'function') {
11
+ callback = encoding;
12
+ encoding = undefined;
13
+ }
14
+
15
+ if ($index >= chunks.length) {
16
+ if (typeof callback === 'function') {
17
+ callback();
18
+ }
19
+ return stream;
20
+ } else if (!stream.push(chunks[$index], ...([encoding].filter(Boolean)))) {
21
+ stream.emit('backpressure', {
22
+ sender: stream.sender,
23
+ requestId: stream.requestId
24
+ });
25
+
26
+ const pipedStreams = [].concat(
27
+ (stream._readableState || {}).pipes || stream
28
+ ).filter(Boolean);
29
+
30
+ let listenerCalled = false;
31
+
32
+ const drainListener = () => {
33
+ stream.emit('resume_backpressure', {
34
+ sender: stream.sender,
35
+ requestId: stream.requestId
36
+ });
37
+
38
+ if (listenerCalled) {
39
+ return;
40
+ }
41
+
42
+ listenerCalled = true;
43
+
44
+ for (const stream of pipedStreams) {
45
+ stream.removeListener('drain', drainListener);
46
+ }
47
+
48
+ pushWithBackpressure(stream, chunks, encoding, callback, $index + 1);
49
+ };
50
+
51
+ for (const stream of pipedStreams) {
52
+ stream.once('drain', drainListener);
53
+ }
54
+
55
+ return stream;
56
+ }
57
+ return pushWithBackpressure(stream, chunks, encoding, callback, $index + 1);
58
+ };
59
+ class InboundTransformStream extends Transform {
60
+ constructor (sender, requestId, options) {
61
+ super(options);
62
+ this.sender = sender;
63
+ this.requestId = requestId;
64
+ }
65
+
66
+ _transform (chunk, encoding, callback) {
67
+ pushWithBackpressure(this, chunk, encoding, callback);
68
+ }
69
+
70
+ _flush (callback) {
71
+ return callback();
72
+ }
73
+ }
74
+
75
+ module.exports = { InboundTransformStream };
@@ -0,0 +1,107 @@
1
+ /*
2
+ * Author: Kevin Ries (kevin.ries@fachwerk.io)
3
+ * -----
4
+ * Copyright 2021 Fachwerk
5
+ */
6
+
7
+ const EventEmitter = require('events').EventEmitter;
8
+
9
+ /**
10
+ * @typedef {Object} AdapterBase
11
+ * @property {string} name Name
12
+ * @property {EventEmitter} bus Event bus.
13
+ * @property {function():Promise<any>} afterInit After init callback.
14
+ * @property {boolean} isConnected Is connected state.
15
+ * @property {number} interruptCounter Interruption counter.
16
+ * @property {number} repeatAttemptCounter Repeat attempt counter
17
+ * @property {function(Object, Object, Object):Promise<any>} init Repeat attempt counter
18
+ */
19
+
20
+ /**
21
+ * Create a adapter base object.
22
+ * @returns {AdapterBase} Adapter base object
23
+ */
24
+ const createTransportBase = () => {
25
+ let prefix = 'weave';
26
+
27
+ return {
28
+ name: null,
29
+ bus: new EventEmitter(),
30
+ afterInit: null,
31
+ isConnected: false,
32
+ interruptCounter: 0,
33
+ repeatAttemptCounter: 0,
34
+ init (broker, transport, messageHandler) {
35
+ this.broker = broker;
36
+ this.transport = transport;
37
+ this.log = transport.log;
38
+ this.messageHandler = messageHandler;
39
+
40
+ if (broker.options.namespace) {
41
+ prefix = `${prefix}-${broker.options.namespace}`;
42
+ }
43
+
44
+ if (this.afterInit) {
45
+ this.afterInit();
46
+ }
47
+
48
+ return Promise.resolve();
49
+ },
50
+ subscribe () {
51
+ return Promise.resolve();
52
+ },
53
+ /**
54
+ *
55
+ * Connection handler
56
+ * @instance
57
+ * @param {*} connectionEventParams Connection event
58
+ * @param {boolean} [startHeartbeatTimers=true] Start timers for this adapter
59
+ * @returns {void}
60
+ */
61
+ connected (connectionEventParams = {}) {
62
+ this.bus.emit('$adapter.connected', connectionEventParams);
63
+ },
64
+ disconnected () {
65
+ this.bus.emit('$adapter.disconnected');
66
+ },
67
+ getTopic (cmd, nodeId) {
68
+ const topic = prefix + '.' + cmd + (nodeId ? '.' + nodeId : '');
69
+ return topic;
70
+ },
71
+ preSend (packet) {
72
+ return this.send(packet);
73
+ },
74
+ send (/* message*/) {
75
+ this.broker.handleError(new Error('Method "send" not implemented.'));
76
+ },
77
+ incomingMessage (messageType, message) {
78
+ const data = this.deserialize(message);
79
+ this.updateStatisticReceived(message.length);
80
+ this.bus.emit('$adapter.message', messageType, data);
81
+ },
82
+ serialize (packet) {
83
+ try {
84
+ // Add the sender to each outgoing message
85
+ packet.payload.sender = this.broker.nodeId;
86
+ return Buffer.from(JSON.stringify(packet));
87
+ } catch (error) {
88
+ this.broker.handleError(error);
89
+ }
90
+ },
91
+ deserialize (packet) {
92
+ try {
93
+ return JSON.parse(packet);
94
+ } catch (error) {
95
+ this.broker.handleError(error);
96
+ }
97
+ },
98
+ updateStatisticReceived (length) {
99
+ this.transport.statistics.received.packages += length;
100
+ },
101
+ updateStatisticSent (length) {
102
+ this.transport.statistics.sent.packages += length;
103
+ }
104
+ };
105
+ };
106
+
107
+ module.exports = createTransportBase;
@@ -1,9 +1,9 @@
1
1
  /*
2
- * Author: Kevin Ries (kevin@fachw3rk.de)
2
+ * Author: Kevin Ries (kevin.ries@fachwerk.io)
3
3
  * -----
4
4
  * Copyright 2019 Fachwerk
5
5
  */
6
6
 
7
- exports.BaseAdapter = require('./adapter-base')
8
- exports.Dummy = require('./dummy')
9
- exports.TCP = require('./tcp')
7
+ exports.BaseAdapter = require('./adapteBase');
8
+ exports.Dummy = require('./dummy');
9
+ exports.TCP = require('./tcp');
@@ -1,42 +1,42 @@
1
1
  /*
2
- * Author: Kevin Ries (kevin@fachw3rk.de)
2
+ * Author: Kevin Ries (kevin.ries@fachwerk.io)
3
3
  * -----
4
4
  * Copyright 2021 Fachwerk
5
5
  */
6
6
 
7
- const TransportBase = require('../adapter-base')
8
- const EventEmitter = require('eventemitter2').EventEmitter2
7
+ const TransportBase = require('../adapteBase');
8
+ const EventEmitter = require('eventemitter2').EventEmitter2;
9
9
 
10
10
  // create a global eventbus to pass messages between weave service brokers.
11
11
  global.bus = new EventEmitter({
12
12
  wildcard: true,
13
13
  maxListeners: 100
14
- })
14
+ });
15
15
 
16
16
  const DummyTransportAdapter = (adapterOptions) => {
17
- const messageBus = global.bus
17
+ const messageBus = global.bus;
18
18
 
19
19
  return Object.assign(TransportBase(adapterOptions), {
20
20
  name: 'Dummy',
21
- connect (isTryReconnect = false) {
22
- this.bus.emit('$adapter.connected', false)
23
- this.log.info('Dummy transport client connected.')
24
- return Promise.resolve()
21
+ connect () {
22
+ this.bus.emit('$adapter.connected', false);
23
+ this.log.info('Dummy transport client connected.');
24
+ return Promise.resolve();
25
25
  },
26
26
  close () {
27
- return Promise.resolve()
27
+ return Promise.resolve();
28
28
  },
29
29
  send (message) {
30
- const data = this.serialize(message)
31
- const topic = this.getTopic(message.type, message.targetNodeId)
32
- messageBus.emit(topic, data)
33
- return Promise.resolve()
30
+ const data = this.serialize(message);
31
+ const topic = this.getTopic(message.type, message.targetNodeId);
32
+ messageBus.emit(topic, data);
33
+ return Promise.resolve();
34
34
  },
35
35
  subscribe (type, nodeId) {
36
- const topic = this.getTopic(type, nodeId)
37
- messageBus.on(topic, message => this.incomingMessage(type, message))
36
+ const topic = this.getTopic(type, nodeId);
37
+ messageBus.on(topic, message => this.incomingMessage(type, message));
38
38
  }
39
- })
40
- }
39
+ });
40
+ };
41
41
 
42
- module.exports = DummyTransportAdapter
42
+ module.exports = DummyTransportAdapter;
@@ -1,35 +1,35 @@
1
1
  /*
2
- * Author: Kevin Ries (kevin@fachw3rk.de)
2
+ * Author: Kevin Ries (kevin.ries@fachwerk.io)
3
3
  * -----
4
4
  * Copyright 2019 Fachwerk
5
5
  */
6
- const { parse } = require('url')
7
- const getAdapterByName = require('./getAdapterByName')
6
+ const { parse } = require('url');
7
+ const getAdapterByName = require('./getAdapterByName');
8
8
 
9
9
  function fromURI (uri) {
10
10
  if (typeof uri !== 'string') {
11
- throw new Error('URI needs to be a string.')
11
+ throw new Error('URI needs to be a string.');
12
12
  }
13
13
 
14
- const urlObject = parse(uri)
14
+ const urlObject = parse(uri);
15
15
 
16
16
  if (!urlObject.protocol) {
17
- throw new Error('Protocol is missing.')
17
+ throw new Error('Protocol is missing.');
18
18
  }
19
19
 
20
- const name = urlObject.protocol.slice(0, -1).toLowerCase()
20
+ const name = urlObject.protocol.slice(0, -1).toLowerCase();
21
21
 
22
- const AdapterFactory = getAdapterByName(name)
22
+ const AdapterFactory = getAdapterByName(name);
23
23
 
24
24
  if (!AdapterFactory) {
25
- throw new Error('No adapter found.')
25
+ throw new Error('No adapter found.');
26
26
  }
27
27
 
28
- let config = null
28
+ let config = null;
29
29
  if (AdapterFactory.uriToConfig) {
30
- config = AdapterFactory.uriToConfig(urlObject)
30
+ config = AdapterFactory.uriToConfig(urlObject);
31
31
  }
32
- return AdapterFactory(config)
32
+ return AdapterFactory(config);
33
33
  }
34
34
 
35
- module.exports = fromURI
35
+ module.exports = fromURI;
@@ -1,11 +1,11 @@
1
- const adapters = require('./adapters')
1
+ const adapters = require('./adapters');
2
2
 
3
3
  module.exports = name => {
4
4
  if (!name) {
5
- return
5
+ return;
6
6
  }
7
- const foundAdapterName = Object.keys(adapters).find(adapter => adapter.toLowerCase() === name.toLowerCase())
7
+ const foundAdapterName = Object.keys(adapters).find(adapter => adapter.toLowerCase() === name.toLowerCase());
8
8
  if (foundAdapterName) {
9
- return adapters[foundAdapterName]
9
+ return adapters[foundAdapterName];
10
10
  }
11
- }
11
+ };
@@ -1,29 +1,29 @@
1
1
  /*
2
- * Author: Kevin Ries (kevin@fachw3rk.de)
2
+ * Author: Kevin Ries (kevin.ries@fachwerk.io)
3
3
  * -----
4
4
  * Copyright 2021 Fachwerk
5
5
  */
6
6
 
7
- const { WeaveBrokerOptionsError } = require('../../errors')
8
- const fromURI = require('./fromURI')
9
- const getAdapterByName = require('./getAdapterByName')
10
- const adapters = require('./adapters')
7
+ const { WeaveBrokerOptionsError } = require('../../errors');
8
+ const fromURI = require('./fromURI');
9
+ const getAdapterByName = require('./getAdapterByName');
10
+ const adapters = require('./adapters');
11
11
 
12
12
  const resolve = (broker, options) => {
13
13
  if (typeof options === 'object') {
14
14
  if (typeof options.adapter === 'string') {
15
- const Adapter = getAdapterByName(options.adapter)
15
+ const Adapter = getAdapterByName(options.adapter);
16
16
 
17
17
  if (Adapter) {
18
- return Adapter(options.options)
18
+ return Adapter(options.options);
19
19
  } else {
20
- broker.handleError(new WeaveBrokerOptionsError(`Invalid transport settings: ${options.adapter}`))
20
+ broker.handleError(new WeaveBrokerOptionsError(`Invalid transport settings: ${options.adapter}`));
21
21
  }
22
22
  }
23
- return options.adapter
23
+ return options.adapter;
24
24
  }
25
25
 
26
- return null
27
- }
26
+ return null;
27
+ };
28
28
 
29
- module.exports = Object.assign({ resolve, fromURI }, adapters)
29
+ module.exports = Object.assign({ resolve, fromURI }, adapters);
@@ -1,10 +1,10 @@
1
1
  module.exports = function createCodec (options) {
2
2
  return {
3
3
  encode (object) {
4
- return Buffer.from(JSON.stringify(object))
4
+ return Buffer.from(JSON.stringify(object));
5
5
  },
6
6
  decode (buffer) {
7
- return JSON.parse(buffer.toString())
7
+ return JSON.parse(buffer.toString());
8
8
  }
9
- }
10
- }
9
+ };
10
+ };
@@ -1,94 +1,96 @@
1
- const dgram = require('dgram')
2
- const { getIpList } = require('@weave-js/utils')
3
- const EventEmitter = require('events').EventEmitter
4
- const Codec = require('./codec')
5
- const { getBroadcastAddresses } = require('../utils')
1
+ const dgram = require('dgram');
2
+ const { getIpList } = require('@weave-js/utils');
3
+ const EventEmitter = require('events').EventEmitter;
4
+ const Codec = require('./codec');
5
+ const { getBroadcastAddresses } = require('../utils');
6
6
  const messageTypes = {
7
7
  HELLO: 4
8
- }
8
+ };
9
9
 
10
10
  const createDiscoveryService = (adapter, options) => {
11
- const namespace = adapter.broker.options.namespace
12
- const codec = Codec(options)
13
- const bus = new EventEmitter()
14
- const ips = getIpList(false)
15
- const MESSAGE_TYPE_LENGHT = 1
11
+ const namespace = adapter.broker.options.namespace;
12
+ const codec = Codec(options);
13
+ const bus = new EventEmitter();
14
+ const ips = getIpList(false);
15
+ const MESSAGE_TYPE_LENGTH = 1;
16
16
 
17
- let servers = []
18
- let discoverTimer
17
+ let servers = [];
18
+ let discoverTimer;
19
19
 
20
20
  const startServer = (host, port, multicastAddress) => {
21
21
  return new Promise((resolve, reject) => {
22
22
  try {
23
- const socket = dgram.createSocket({ type: options.discovery.type, reuseAddr: options.discovery.udpReuseAddress })
24
-
25
- socket.on('message', (message, info) => {
26
- const messageType = Buffer.prototype.readUInt8.call(message, 0)
27
- const payload = message.slice(MESSAGE_TYPE_LENGHT)
28
-
29
- switch (messageType) {
30
- case messageTypes.HELLO:
31
- onMessage(payload, info)
32
- break
33
- default:
34
- onUnknown(payload, info)
35
- }
36
- })
23
+ const socket = dgram.createSocket({
24
+ type: options.discovery.type,
25
+ reuseAddr: options.discovery.udpReuseAddress
26
+ });
27
+
28
+ socket.on('message', onMessage);
37
29
 
38
- socket.bind({ port, host, exclusive: true }, () => {
30
+ socket.bind({ port, exclusive: true }, () => {
39
31
  try {
40
32
  if (multicastAddress) {
41
- socket.setMulticastInterface(host)
42
- socket.addMembership(multicastAddress, host)
43
- socket.setMulticastTTL(1)
44
- socket.destinations = [multicastAddress]
45
- adapter.log.info(`UDP Server is listening on ${host}:${port}. Membership: ${multicastAddress}`)
33
+ socket.setMulticastInterface(host);
34
+ socket.addMembership(multicastAddress, host);
35
+ socket.setMulticastTTL(1);
36
+ // Add destination to socket object
37
+ Object.defineProperty(socket, 'destinations', {
38
+ value: [multicastAddress]
39
+ });
40
+ adapter.log.info(`UDP Server is listening on ${host}:${port}. Membership: ${multicastAddress}`);
46
41
  } else {
47
- socket.setBroadcast(true)
48
- socket.destinations = getBroadcastAddresses()
42
+ socket.setBroadcast(true);
43
+ Object.defineProperty(socket, 'destinations', {
44
+ value: getBroadcastAddresses()
45
+ });
49
46
  }
50
47
  } catch (error) {
51
- adapter.log.info(`UDP Multicast membership error: ${error.message}`)
48
+ adapter.log.info(`UDP Multicast membership error: ${error.message}`);
52
49
  }
53
- })
50
+ });
54
51
 
55
- servers.push(socket)
52
+ servers.push(socket);
56
53
 
57
- resolve(socket)
54
+ resolve(socket);
58
55
  } catch (error) {
59
- reject(error)
56
+ reject(error);
60
57
  }
61
- })
62
- }
58
+ });
59
+ };
63
60
 
64
61
  const onMessage = (buffer, info) => {
65
- const message = codec.decode(buffer)
66
- message.host = info.address
62
+ const messageType = Buffer.prototype.readUInt8.call(buffer, 0);
63
+ const payload = buffer.slice(MESSAGE_TYPE_LENGTH);
67
64
 
68
- if (message.namespace === namespace) {
69
- bus.emit('message', message)
70
- }
71
- }
65
+ switch (messageType) {
66
+ case messageTypes.HELLO:
67
+ const message = codec.decode(payload);
68
+ message.host = info.address;
72
69
 
73
- const onUnknown = (message, info) => {
74
- adapter.log.debug(`Received an unknown data package from host "${info.address}"`)
75
- }
70
+ if (message.namespace === namespace) {
71
+ bus.emit('message', message);
72
+ }
73
+ break;
74
+ default:
75
+ adapter.log.debug(`Received an unknown data package from host "${info.address}"`);
76
+ }
77
+ };
76
78
 
77
79
  function sendMessage (payload) {
78
- const header = Buffer.alloc(MESSAGE_TYPE_LENGHT)
79
- Buffer.prototype.writeUInt8.call(header, messageTypes.HELLO, 0)
80
+ const header = Buffer.alloc(MESSAGE_TYPE_LENGTH);
81
+ Buffer.prototype.writeUInt8.call(header, messageTypes.HELLO, 0);
80
82
 
81
- const message = Buffer.concat([header, codec.encode(payload)])
83
+ const message = Buffer.concat([header, codec.encode(payload)]);
82
84
 
83
85
  servers.forEach(server => {
84
86
  server.destinations.forEach(host => {
85
87
  server.send(message, options.discovery.port, host, (error) => {
86
88
  if (!error) {
87
- adapter.log.verbose(`Message sent to ${host}:${options.discovery.port}`)
89
+ adapter.log.verbose(`Message sent to ${host}:${options.discovery.port}`);
88
90
  }
89
- })
90
- })
91
- })
91
+ });
92
+ });
93
+ });
92
94
  }
93
95
 
94
96
  function sendDiscoveryPackage (port) {
@@ -96,40 +98,52 @@ const createDiscoveryService = (adapter, options) => {
96
98
  namespace: adapter.broker.options.namespace,
97
99
  nodeId: adapter.broker.nodeId,
98
100
  port: port
99
- })
101
+ });
100
102
  }
101
103
 
102
104
  function startDiscovering (port) {
103
- discoverTimer = setInterval(() => sendDiscoveryPackage(port), 2000)
104
-
105
- discoverTimer.unref()
105
+ discoverTimer = setInterval(() => sendDiscoveryPackage(port), 2000);
106
+ discoverTimer.unref();
106
107
  }
107
108
 
108
109
  function stopDiscovery () {
109
110
  if (discoverTimer) {
110
- clearInterval(discoverTimer)
111
- discoverTimer = null
112
- adapter.log.info('UDP discovery service stopped')
111
+ clearInterval(discoverTimer);
112
+ discoverTimer = null;
113
+ adapter.log.info('UDP discovery service stopped');
113
114
  }
114
115
  }
115
116
 
116
117
  return {
117
118
  bus,
118
- init (port) {
119
+ async start (port) {
119
120
  if (!options.discovery.enabled) {
120
- return Promise.resolve()
121
+ return Promise.resolve();
122
+ }
123
+
124
+ // UDP Multicast
125
+ if (options.discovery.udpMulticast) {
126
+ if (options.discovery.multicastAddress) {
127
+ await Promise.all(ips.map(ip => startServer(ip, options.discovery.port, options.discovery.multicastAddress)));
128
+ }
121
129
  }
122
130
 
123
- return Promise.all(ips.map(ip => startServer(ip, options.discovery.port, options.discovery.multicastAddress)))
124
- .then(() => setTimeout(() => sendDiscoveryPackage(port), Math.floor(Math.random() * 500) + 1))
125
- .then(() => startDiscovering(port))
131
+ // UDP Broadcast
132
+ if (options.discovery.udpBroadcast) {
133
+ await startServer(options.discovery.udpBindAddress, options.discovery.port, options.discovery.multicastAddress);
134
+ }
135
+
136
+ // send the first dis
137
+ const timeout = Math.floor(Math.random() * 500) + 500;
138
+ setTimeout(() => sendDiscoveryPackage(port), timeout);
139
+ startDiscovering(port);
126
140
  },
127
141
  close () {
128
- stopDiscovery()
129
- servers.forEach(server => server.close())
130
- servers = []
142
+ stopDiscovery();
143
+ servers.forEach(server => server.close());
144
+ servers = [];
131
145
  }
132
- }
133
- }
146
+ };
147
+ };
134
148
 
135
- module.exports = createDiscoveryService
149
+ module.exports = createDiscoveryService;