@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.
- package/.eslintrc.js +1 -1
- package/jest.config.js +1 -1
- package/lib/ExtendableError.js +33 -0
- package/lib/broker/context.js +58 -46
- package/lib/broker/{default-options.js → defaultOptions.js} +31 -13
- package/lib/broker/index.js +273 -251
- package/lib/buildRuntime.js +70 -0
- package/lib/cache/adapters/base.js +119 -0
- package/lib/cache/adapters/inMemory.js +154 -0
- package/lib/cache/adapters/inMemoryLru.js +140 -0
- package/lib/cache/adapters/index.js +10 -0
- package/lib/cache/getCacheKeyByObject.js +31 -0
- package/lib/cache/getPropertyFromDataOrMetadata.js +20 -0
- package/lib/cache/lock.js +34 -11
- package/lib/constants.js +11 -8
- package/lib/{error-handler.js → errorHandler.js} +8 -8
- package/lib/errors.js +46 -39
- package/lib/helper/{define-action.js → defineAction.js} +5 -3
- package/lib/helper/{define-broker-options.js → defineBrokerOptions.js} +4 -2
- package/lib/helper/{define-service.js → defineService.js} +6 -3
- package/lib/index.js +25 -22
- package/lib/logger/base.js +38 -29
- package/lib/logger/format/asHumanReadable.js +15 -14
- package/lib/logger/format/asJson.js +10 -10
- package/lib/logger/format/index.js +3 -3
- package/lib/logger/index.js +28 -25
- package/lib/logger/levels.js +23 -22
- package/lib/logger/tools.js +17 -13
- package/lib/logger/utils/colorize.js +23 -23
- package/lib/logger/utils/format.js +89 -65
- package/lib/metrics/common.js +47 -47
- package/lib/metrics/constants.js +44 -44
- package/lib/metrics/exporter/base.js +8 -8
- package/lib/metrics/exporter/event.js +20 -20
- package/lib/metrics/exporter/index.js +15 -15
- package/lib/metrics/index.js +2 -2
- package/lib/metrics/types/base.js +20 -20
- package/lib/metrics/types/counter.js +6 -6
- package/lib/metrics/types/gauge.js +24 -24
- package/lib/metrics/types/histogram.js +26 -26
- package/lib/metrics/types/index.js +6 -6
- package/lib/metrics/types/info.js +17 -17
- package/lib/middlewares/action-hooks/index.js +82 -34
- package/lib/middlewares/bulkhead/index.js +34 -33
- package/lib/middlewares/cache/index.js +106 -0
- package/lib/middlewares/circuit-breaker/index.js +85 -60
- package/lib/middlewares/context-tracker/index.js +39 -39
- package/lib/middlewares/error-handler/index.js +14 -14
- package/lib/middlewares/index.js +3 -2
- package/lib/middlewares/metrics/getMiddlewareWrapper.js +17 -17
- package/lib/middlewares/metrics/index.js +29 -29
- package/lib/middlewares/retry/index.js +15 -15
- package/lib/middlewares/timeout/index.js +18 -18
- package/lib/middlewares/tracing/index.js +50 -37
- package/lib/middlewares/tracing/tags.js +43 -0
- package/lib/middlewares/validator/index.js +32 -32
- package/lib/registry/{action-endpoint.js → actionEndpoint.js} +8 -8
- package/lib/registry/collections/{action-collection.js → actionCollection.js} +39 -35
- package/lib/registry/collections/{endpoint-collection.js → endpointCollection.js} +64 -65
- package/lib/registry/collections/{event-collection.js → eventCollection.js} +65 -69
- package/lib/registry/collections/{node-collection.js → nodeCollection.js} +45 -45
- package/lib/registry/collections/{service-collection.js → serviceCollection.js} +61 -55
- package/lib/registry/eventEndpoint.js +26 -0
- package/lib/registry/load-balancer/base.js +3 -3
- package/lib/registry/load-balancer/index.js +7 -7
- package/lib/registry/node.js +27 -27
- package/lib/registry/registry.js +147 -163
- package/lib/registry/service/parseAction.js +16 -16
- package/lib/registry/service/parseEvent.js +18 -18
- package/lib/registry/service/reduceMixins.js +10 -10
- package/lib/registry/service/service.js +72 -72
- package/lib/registry/{service-item.js → serviceItem.js} +21 -21
- package/lib/runtime/{init-action-invoker.js → initActionInvoker.js} +21 -21
- package/lib/runtime/initCache.js +19 -0
- package/lib/runtime/{init-context-factory.js → initContextFactory.js} +22 -22
- package/lib/runtime/{init-eventbus.js → initEventbus.js} +54 -53
- package/lib/runtime/{init-logger.js → initLogger.js} +11 -11
- package/lib/runtime/{init-metrics.js → initMetrics.js} +55 -54
- package/lib/runtime/{init-middleware-manager.js → initMiddlewareManager.js} +21 -21
- package/lib/runtime/{init-registry.js → initRegistry.js} +6 -6
- package/lib/runtime/initServiceManager.js +145 -0
- package/lib/runtime/{init-tracing.js → initTracing.js} +25 -24
- package/lib/runtime/{init-transport.js → initTransport.js} +5 -5
- package/lib/runtime/{init-uuid-factory.js → initUuidFactory.js} +4 -4
- package/lib/runtime/{init-validator.js → initValidator.js} +5 -5
- package/lib/tracing/collectors/base.js +29 -37
- package/lib/tracing/collectors/event.js +33 -33
- package/lib/tracing/collectors/index.js +16 -16
- package/lib/tracing/span.js +34 -32
- package/lib/tracing/time.js +8 -8
- package/lib/transport/InboundTransformStream.js +75 -0
- package/lib/transport/adapters/adapteBase.js +107 -0
- package/lib/transport/adapters/adapters.js +4 -4
- package/lib/transport/adapters/dummy/index.js +19 -19
- package/lib/transport/adapters/fromURI.js +13 -13
- package/lib/transport/adapters/getAdapterByName.js +5 -5
- package/lib/transport/adapters/index.js +12 -12
- package/lib/transport/adapters/tcp/discovery/codec.js +4 -4
- package/lib/transport/adapters/tcp/discovery/index.js +90 -76
- package/lib/transport/adapters/tcp/index.js +180 -175
- package/lib/transport/adapters/tcp/tcp-messagetypes.js +7 -7
- package/lib/transport/adapters/tcp/tcpReader.js +39 -38
- package/lib/transport/adapters/tcp/tcpWriteStream.js +26 -26
- package/lib/transport/adapters/tcp/tcpWriter.js +58 -58
- package/lib/transport/adapters/tcp/utils.js +12 -12
- package/lib/transport/createMessage.js +11 -0
- package/lib/transport/createTransport.js +377 -334
- package/lib/transport/errorPayloadFactory.js +15 -0
- package/lib/transport/messageHandlers.js +517 -0
- package/lib/transport/messageTypes.js +23 -0
- package/lib/types.js +95 -71
- package/lib/utils/index.js +2 -2
- package/lib/utils/options.js +47 -45
- package/lib/utils/{restore-error.js → restoreError.js} +4 -4
- package/package.json +6 -12
- package/CHANGELOG.md +0 -1334
- package/lib/build-runtime.js +0 -70
- package/lib/cache/base.js +0 -142
- package/lib/cache/index.js +0 -48
- package/lib/cache/memory.js +0 -121
- package/lib/middlewares/tracing/buildTags.js +0 -17
- package/lib/new-errors.js +0 -25
- package/lib/registry/event-endpoint.js +0 -26
- package/lib/runtime/init-cache.js +0 -10
- package/lib/runtime/init-service-manager.js +0 -128
- package/lib/tracing/collectors/console.js +0 -34
- package/lib/tracing/index.js +0 -3
- package/lib/tracing/tracer.js +0 -64
- package/lib/transport/adapters/adapter-base.js +0 -92
- package/lib/transport/message-handlers.js +0 -448
- package/lib/transport/message-types.js +0 -59
- package/lib/transport/message.js +0 -16
package/lib/tracing/time.js
CHANGED
|
@@ -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@
|
|
2
|
+
* Author: Kevin Ries (kevin.ries@fachwerk.io)
|
|
3
3
|
* -----
|
|
4
4
|
* Copyright 2019 Fachwerk
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
exports.BaseAdapter = require('./
|
|
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@
|
|
2
|
+
* Author: Kevin Ries (kevin.ries@fachwerk.io)
|
|
3
3
|
* -----
|
|
4
4
|
* Copyright 2021 Fachwerk
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const TransportBase = require('../
|
|
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 (
|
|
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@
|
|
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@
|
|
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
|
|
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({
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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,
|
|
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
|
|
45
|
-
|
|
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
|
|
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
|
|
66
|
-
|
|
62
|
+
const messageType = Buffer.prototype.readUInt8.call(buffer, 0);
|
|
63
|
+
const payload = buffer.slice(MESSAGE_TYPE_LENGTH);
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
65
|
+
switch (messageType) {
|
|
66
|
+
case messageTypes.HELLO:
|
|
67
|
+
const message = codec.decode(payload);
|
|
68
|
+
message.host = info.address;
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
124
|
-
|
|
125
|
-
.
|
|
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;
|