@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/broker/index.js
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
// node packages
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const Middlewares = require('../middlewares')
|
|
9
|
+
const { isFunction } = require('@weave-js/utils');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const glob = require('glob');
|
|
12
|
+
const Middlewares = require('../middlewares');
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Creates a new Weave Broker instance
|
|
@@ -28,353 +28,375 @@ exports.createBrokerInstance = (runtime) => {
|
|
|
28
28
|
validator,
|
|
29
29
|
log,
|
|
30
30
|
services,
|
|
31
|
-
transport
|
|
32
|
-
|
|
33
|
-
cache
|
|
34
|
-
} = runtime
|
|
31
|
+
transport
|
|
32
|
+
} = runtime;
|
|
35
33
|
|
|
36
34
|
// Log Messages
|
|
37
|
-
log.info(`Initializing #weave node version ${version}`)
|
|
38
|
-
log.info(`Node Id: ${options.nodeId}`)
|
|
35
|
+
log.info(`Initializing #weave node version ${version}`);
|
|
36
|
+
log.info(`Node Id: ${options.nodeId}`);
|
|
39
37
|
|
|
38
|
+
// Output namespace
|
|
40
39
|
if (options.namespace) {
|
|
41
|
-
log.info(`Namespace: ${options.namespace}`)
|
|
40
|
+
log.info(`Namespace: ${options.namespace}`);
|
|
42
41
|
}
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
// Init metrics
|
|
44
|
+
if (runtime.metrics) {
|
|
45
|
+
runtime.metrics.init();
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
// Init cache
|
|
49
|
+
if (runtime.cache) {
|
|
50
|
+
runtime.cache.init();
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
// broker object
|
|
53
54
|
/** @type {Broker} */
|
|
54
|
-
const broker =
|
|
55
|
-
nodeId: options.nodeId,
|
|
56
|
-
version,
|
|
57
|
-
options,
|
|
58
|
-
runtime,
|
|
59
|
-
bus,
|
|
60
|
-
validator,
|
|
61
|
-
contextFactory,
|
|
62
|
-
log,
|
|
63
|
-
createLogger: runtime.createLogger,
|
|
64
|
-
getUUID: () => runtime.generateUUID(),
|
|
65
|
-
registry,
|
|
66
|
-
getNextActionEndpoint (actionName, options = {}) {
|
|
67
|
-
return registry.getNextAvailableActionEndpoint(actionName, options)
|
|
68
|
-
},
|
|
69
|
-
emit: eventBus.emit.bind(this),
|
|
70
|
-
broadcast: eventBus.broadcast.bind(this),
|
|
71
|
-
broadcastLocal: eventBus.broadcastLocal.bind(this),
|
|
72
|
-
call: runtime.actionInvoker.call.bind(this),
|
|
73
|
-
multiCall: runtime.actionInvoker.multiCall.bind(this),
|
|
74
|
-
waitForServices: services.waitForServices.bind(this),
|
|
75
|
-
createService: services.createService.bind(this),
|
|
76
|
-
/**
|
|
77
|
-
* Load and register a service from file.
|
|
78
|
-
* @param {string} fileName Path to the service file.
|
|
79
|
-
* @returns {Service} Service
|
|
80
|
-
*/
|
|
81
|
-
loadService (fileName) {
|
|
82
|
-
const filePath = path.resolve(fileName)
|
|
83
|
-
const schema = require(filePath)
|
|
84
|
-
const service = this.createService(schema)
|
|
85
|
-
|
|
86
|
-
// If the "watchSevrices" option is set - add service to service watcher.
|
|
87
|
-
if (options.watchServices) {
|
|
88
|
-
service.filename = fileName
|
|
89
|
-
services.watchService.call(this, service)
|
|
90
|
-
}
|
|
55
|
+
const broker = Object.create(null);
|
|
91
56
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
log.info(`Searching services in folder '${folder}' with name pattern '${fileMask}'.`)
|
|
104
|
-
log.info(`${serviceFiles.length} services found.`)
|
|
105
|
-
|
|
106
|
-
serviceFiles.forEach(fileName => this.loadService(fileName))
|
|
107
|
-
return serviceFiles.length
|
|
108
|
-
},
|
|
109
|
-
/**
|
|
110
|
-
* Starts the broker.
|
|
111
|
-
* @returns {Promise} Promise
|
|
112
|
-
*/
|
|
113
|
-
async start () {
|
|
114
|
-
const startTime = Date.now()
|
|
115
|
-
await middlewareHandler.callHandlersAsync('starting', [runtime], true)
|
|
116
|
-
|
|
117
|
-
if (transport) {
|
|
118
|
-
await transport.connect()
|
|
119
|
-
}
|
|
57
|
+
broker.runtime = runtime;
|
|
58
|
+
broker.registry = registry;
|
|
59
|
+
broker.bus = bus;
|
|
60
|
+
broker.nodeId = options.nodeId;
|
|
61
|
+
broker.version = version;
|
|
62
|
+
broker.options = options;
|
|
63
|
+
broker.validator = validator;
|
|
64
|
+
broker.contextFactory = contextFactory;
|
|
65
|
+
broker.log = log;
|
|
66
|
+
broker.createLogger = runtime.createLogger;
|
|
120
67
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
log.error(error, 'Unable to start all services')
|
|
125
|
-
clearInterval(options.waitForServiceInterval)
|
|
126
|
-
throw error
|
|
127
|
-
}
|
|
68
|
+
broker.getUUID = function () {
|
|
69
|
+
return runtime.generateUUID();
|
|
70
|
+
};
|
|
128
71
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
72
|
+
broker.getNextActionEndpoint = function (actionName, options = {}) {
|
|
73
|
+
return registry.getNextAvailableActionEndpoint(actionName, options);
|
|
74
|
+
};
|
|
132
75
|
|
|
133
|
-
|
|
134
|
-
await transport.setReady()
|
|
135
|
-
}
|
|
76
|
+
broker.emit = eventBus.emit.bind(broker);
|
|
136
77
|
|
|
137
|
-
|
|
78
|
+
broker.broadcast = eventBus.broadcast.bind(broker);
|
|
138
79
|
|
|
139
|
-
|
|
140
|
-
options.started.call(this)
|
|
141
|
-
}
|
|
80
|
+
broker.broadcastLocal = eventBus.broadcastLocal.bind(broker);
|
|
142
81
|
|
|
143
|
-
|
|
144
|
-
log.info(`Node "${options.nodeId}" with ${services.serviceList.length} services successfully started in ${duration}ms.`)
|
|
145
|
-
},
|
|
146
|
-
/**
|
|
147
|
-
* Stops the broker.
|
|
148
|
-
* @returns {Promise} Promise
|
|
149
|
-
*/
|
|
150
|
-
async stop () {
|
|
151
|
-
runtime.state.isStarted = false
|
|
152
|
-
log.info('Shutting down the node...')
|
|
153
|
-
|
|
154
|
-
await middlewareHandler.callHandlersAsync('stopping', [runtime], true)
|
|
155
|
-
|
|
156
|
-
try {
|
|
157
|
-
await Promise.all(services.serviceList.map(service => service.stop()))
|
|
158
|
-
} catch (error) {
|
|
159
|
-
log.error(error, 'Unable to stop all services.')
|
|
160
|
-
throw error
|
|
161
|
-
}
|
|
82
|
+
broker.call = runtime.actionInvoker.call.bind(broker);
|
|
162
83
|
|
|
163
|
-
|
|
164
|
-
await transport.disconnect()
|
|
165
|
-
}
|
|
84
|
+
broker.multiCall = runtime.actionInvoker.multiCall.bind(broker);
|
|
166
85
|
|
|
167
|
-
|
|
168
|
-
log.debug('Stopping caching adapters.')
|
|
169
|
-
await runtime.cache.stop()
|
|
170
|
-
}
|
|
86
|
+
broker.waitForServices = services.waitForServices.bind(broker);
|
|
171
87
|
|
|
172
|
-
|
|
173
|
-
log.debug('Stopping metrics.')
|
|
174
|
-
await runtime.metrics.stop()
|
|
175
|
-
}
|
|
88
|
+
broker.createService = services.createService.bind(broker);
|
|
176
89
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Global error handler of the broker.
|
|
92
|
+
* @param {*} error Error
|
|
93
|
+
* @returns {void}
|
|
94
|
+
*/
|
|
95
|
+
broker.handleError = runtime.handleError;
|
|
181
96
|
|
|
182
|
-
|
|
97
|
+
broker.fatalError = runtime.fatalError;
|
|
183
98
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
99
|
+
/**
|
|
100
|
+
* Load and register a service from file.
|
|
101
|
+
* @param {string} filename Path to the service file.
|
|
102
|
+
* @returns {Service} Service
|
|
103
|
+
*/
|
|
104
|
+
broker.loadService = function (filename) {
|
|
105
|
+
const filePath = path.resolve(filename);
|
|
106
|
+
const schema = require(filePath);
|
|
107
|
+
const service = broker.createService(schema);
|
|
108
|
+
|
|
109
|
+
if (service) {
|
|
110
|
+
service.filename = filename;
|
|
111
|
+
}
|
|
187
112
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
eventBus.broadcastLocal('$broker.stopped')
|
|
191
|
-
|
|
192
|
-
process.removeListener('beforeExit', onClose)
|
|
193
|
-
process.removeListener('exit', onClose)
|
|
194
|
-
process.removeListener('SIGINT', onClose)
|
|
195
|
-
process.removeListener('SIGTERM', onClose)
|
|
196
|
-
|
|
197
|
-
// todo: handle errors
|
|
198
|
-
},
|
|
199
|
-
/**
|
|
200
|
-
* Send a ping to connected nodes.
|
|
201
|
-
* @param {*} nodeId Node id
|
|
202
|
-
* @param {number} [timeout=3000] Ping timeout
|
|
203
|
-
* @returns {Array} Ping result
|
|
204
|
-
*/
|
|
205
|
-
ping (nodeId, timeout = 3000) {
|
|
206
|
-
if (transport && transport.isConnected) {
|
|
207
|
-
if (nodeId) {
|
|
208
|
-
return new Promise((resolve) => {
|
|
209
|
-
const timeoutTimer = setTimeout(() => {
|
|
210
|
-
bus.off('$node.pong', pongHandler)
|
|
211
|
-
return resolve(null)
|
|
212
|
-
}, timeout)
|
|
213
|
-
|
|
214
|
-
const pongHandler = pong => {
|
|
215
|
-
clearTimeout(timeoutTimer)
|
|
216
|
-
bus.off('$node.pong', pongHandler)
|
|
217
|
-
resolve(pong)
|
|
218
|
-
}
|
|
113
|
+
return service;
|
|
114
|
+
};
|
|
219
115
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
116
|
+
broker.loadServices = function (folder = './services', fileMask = '*.service.js') {
|
|
117
|
+
const serviceFiles = glob.sync(path.join(folder, fileMask));
|
|
118
|
+
|
|
119
|
+
log.info(`Searching services in folder '${folder}' with name pattern '${fileMask}'.`);
|
|
120
|
+
log.info(`${serviceFiles.length} services found.`);
|
|
121
|
+
|
|
122
|
+
serviceFiles.forEach(fileName => broker.loadService(fileName));
|
|
123
|
+
return serviceFiles.length;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Starts the broker.
|
|
128
|
+
* @returns {Promise} Promise
|
|
129
|
+
*/
|
|
130
|
+
broker.start = async function () {
|
|
131
|
+
const startTime = Date.now();
|
|
132
|
+
await middlewareHandler.callHandlersAsync('starting', [runtime], true);
|
|
133
|
+
|
|
134
|
+
// If transport is used, we connect the transport adapter.
|
|
135
|
+
if (transport) {
|
|
136
|
+
await transport.connect();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
await Promise.all(services.serviceList.map(service => service.start()));
|
|
141
|
+
} catch (error) {
|
|
142
|
+
log.error(error, 'Unable to start all services');
|
|
143
|
+
clearInterval(options.waitForServiceInterval);
|
|
144
|
+
throw error;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
runtime.state.isStarted = true;
|
|
148
|
+
eventBus.broadcastLocal('$broker.started');
|
|
149
|
+
// refresh local node information
|
|
150
|
+
registry.generateLocalNodeInfo(true);
|
|
151
|
+
|
|
152
|
+
// If transport is used, we set the transport ready to inform the other nodes
|
|
153
|
+
if (transport) {
|
|
154
|
+
await transport.setReady();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
await middlewareHandler.callHandlersAsync('started', [runtime], true);
|
|
158
|
+
|
|
159
|
+
if (runtime.state.isStarted && isFunction(options.started)) {
|
|
160
|
+
options.started.call(broker);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const duration = Date.now() - startTime;
|
|
164
|
+
log.info(`Node "${options.nodeId}" with ${services.serviceList.length} services successfully started in ${duration}ms.`);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Stops the broker.
|
|
169
|
+
* @returns {Promise} Promise
|
|
170
|
+
*/
|
|
171
|
+
broker.stop = async function () {
|
|
172
|
+
runtime.state.isStarted = false;
|
|
173
|
+
log.info('Shutting down the node...');
|
|
174
|
+
|
|
175
|
+
await middlewareHandler.callHandlersAsync('stopping', [runtime], true);
|
|
176
|
+
|
|
177
|
+
// Stop services
|
|
178
|
+
try {
|
|
179
|
+
await Promise.all(services.serviceList.map(service => service.stop()));
|
|
180
|
+
} catch (error) {
|
|
181
|
+
log.error(error, 'Unable to stop all services.');
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Disconnect transports
|
|
186
|
+
if (transport) {
|
|
187
|
+
await transport.disconnect();
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Stop cache
|
|
191
|
+
if (runtime.cache) {
|
|
192
|
+
log.debug('Stopping caching adapters.');
|
|
193
|
+
await runtime.cache.stop();
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Stop metrics
|
|
197
|
+
if (runtime.metrics) {
|
|
198
|
+
log.debug('Stopping metrics.');
|
|
199
|
+
await runtime.metrics.stop();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Stop tracers
|
|
203
|
+
if (runtime.tracer) {
|
|
204
|
+
log.debug('Stopping tracing adapters.');
|
|
205
|
+
await runtime.tracer.stop();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Call "stopped" middleware method.
|
|
209
|
+
await middlewareHandler.callHandlersAsync('stopped', [runtime], true);
|
|
210
|
+
|
|
211
|
+
// Call "stopped" lifecycle hook
|
|
212
|
+
if (!runtime.state.isStarted && isFunction(options.stopped)) {
|
|
213
|
+
options.stopped.call(runtime);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
log.info('The node was successfully shut down. Bye bye! 👋');
|
|
217
|
+
|
|
218
|
+
eventBus.broadcastLocal('$broker.stopped');
|
|
219
|
+
|
|
220
|
+
process.removeListener('beforeExit', onClose);
|
|
221
|
+
process.removeListener('exit', onClose);
|
|
222
|
+
process.removeListener('SIGINT', onClose);
|
|
223
|
+
process.removeListener('SIGTERM', onClose);
|
|
224
|
+
|
|
225
|
+
// todo: handle errors
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Ping other nodes
|
|
230
|
+
* @param {string=} nodeId Node ID
|
|
231
|
+
* @param {number} timeout Timeout
|
|
232
|
+
* @returns {Object<string, number>} Result
|
|
233
|
+
*/
|
|
234
|
+
broker.ping = function (nodeId, timeout = 3000) {
|
|
235
|
+
if (transport && transport.isConnected) {
|
|
236
|
+
if (nodeId) {
|
|
237
|
+
return new Promise((resolve) => {
|
|
238
|
+
const timeoutTimer = setTimeout(() => {
|
|
239
|
+
bus.off('$node.pong', pongHandler);
|
|
240
|
+
return resolve(null);
|
|
241
|
+
}, timeout);
|
|
242
|
+
|
|
243
|
+
const pongHandler = pong => {
|
|
244
|
+
clearTimeout(timeoutTimer);
|
|
245
|
+
bus.off('$node.pong', pongHandler);
|
|
246
|
+
resolve(pong);
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
bus.on('$node.pong', pongHandler);
|
|
250
|
+
transport.sendPing(nodeId);
|
|
251
|
+
});
|
|
252
|
+
} else {
|
|
253
|
+
// handle arrays
|
|
254
|
+
const pongs = {};
|
|
255
|
+
|
|
256
|
+
const nodes = registry.nodeCollection.list({})
|
|
257
|
+
.filter(node => !node.isLocal)
|
|
258
|
+
.map(node => node.id);
|
|
259
|
+
|
|
260
|
+
const onFlight = new Set(nodes);
|
|
261
|
+
|
|
262
|
+
nodes.forEach(nodeId => {
|
|
263
|
+
pongs[nodeId] = null;
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
return new Promise((resolve) => {
|
|
267
|
+
// todo: handle timeout
|
|
268
|
+
const timeoutTimer = setTimeout(() => {
|
|
269
|
+
bus.off('$node.pong', pongHandler);
|
|
270
|
+
resolve(pongs);
|
|
271
|
+
}, timeout);
|
|
272
|
+
|
|
273
|
+
const pongHandler = pong => {
|
|
274
|
+
pongs[pong.nodeId] = pong;
|
|
275
|
+
onFlight.delete(pong.nodeId);
|
|
276
|
+
if (onFlight.size === 0) {
|
|
277
|
+
clearTimeout(timeoutTimer);
|
|
278
|
+
bus.off('$node.pong', pongHandler);
|
|
279
|
+
resolve(pongs);
|
|
252
280
|
}
|
|
281
|
+
};
|
|
253
282
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
283
|
+
bus.on('$node.pong', pongHandler);
|
|
284
|
+
nodes.map(nodeId => transport.sendPing(nodeId));
|
|
285
|
+
});
|
|
258
286
|
}
|
|
287
|
+
}
|
|
259
288
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
/**
|
|
263
|
-
* Global error handler of the broker.
|
|
264
|
-
* @param {*} error Error
|
|
265
|
-
* @returns {void}
|
|
266
|
-
*/
|
|
267
|
-
handleError: runtime.handleError,
|
|
268
|
-
fatalError: runtime.fatalError
|
|
269
|
-
}
|
|
289
|
+
return Promise.resolve(nodeId ? null : {});
|
|
290
|
+
};
|
|
270
291
|
|
|
271
292
|
// Register internal broker events
|
|
272
293
|
broker.bus.on('$node.disconnected', ({ nodeId }) => {
|
|
273
|
-
runtime.transport.removePendingRequestsByNodeId(nodeId)
|
|
274
|
-
services.serviceChanged(false)
|
|
275
|
-
})
|
|
294
|
+
runtime.transport.removePendingRequestsByNodeId(nodeId);
|
|
295
|
+
services.serviceChanged(false);
|
|
296
|
+
});
|
|
276
297
|
|
|
277
298
|
/**
|
|
278
299
|
* Register middlewares
|
|
279
300
|
* @param {Array<Object>} customMiddlewares Array of user defined middlewares
|
|
280
301
|
* @returns {void}
|
|
281
302
|
*/
|
|
282
|
-
const registerMiddlewares = customMiddlewares => {
|
|
303
|
+
const registerMiddlewares = (customMiddlewares) => {
|
|
283
304
|
// Register custom middlewares
|
|
284
305
|
if (Array.isArray(customMiddlewares) && customMiddlewares.length > 0) {
|
|
285
|
-
customMiddlewares.forEach(middleware => middlewareHandler.add(middleware))
|
|
306
|
+
customMiddlewares.forEach(middleware => middlewareHandler.add(middleware));
|
|
286
307
|
}
|
|
287
308
|
|
|
288
309
|
// Add the built-in middlewares. (The order is important)
|
|
289
310
|
if (options.loadInternalMiddlewares) {
|
|
290
|
-
middlewareHandler.add(Middlewares.ActionHooks)
|
|
311
|
+
middlewareHandler.add(Middlewares.ActionHooks);
|
|
291
312
|
|
|
292
313
|
// Validator middleware
|
|
293
314
|
if (options.validateActionParams && validator) {
|
|
294
|
-
middlewareHandler.add(Middlewares.Validator)
|
|
315
|
+
middlewareHandler.add(Middlewares.Validator);
|
|
295
316
|
}
|
|
296
317
|
|
|
297
318
|
// Bulkhead
|
|
298
319
|
if (options.bulkhead.enabled) {
|
|
299
|
-
middlewareHandler.add(Middlewares.Bulkhead)
|
|
320
|
+
middlewareHandler.add(Middlewares.Bulkhead);
|
|
300
321
|
}
|
|
301
322
|
|
|
302
323
|
// Cache
|
|
303
324
|
if (runtime.cache) {
|
|
304
|
-
middlewareHandler.add(
|
|
325
|
+
middlewareHandler.add(Middlewares.Cache);
|
|
305
326
|
}
|
|
306
327
|
|
|
307
328
|
// Context tracking
|
|
308
329
|
if (options.contextTracking.enabled) {
|
|
309
|
-
middlewareHandler.add(Middlewares.ContextTracker)
|
|
330
|
+
middlewareHandler.add(Middlewares.ContextTracker);
|
|
310
331
|
}
|
|
311
332
|
|
|
312
333
|
// Circuit breaker
|
|
313
334
|
if (options.circuitBreaker.enabled) {
|
|
314
|
-
middlewareHandler.add(Middlewares.CircuitBreaker)
|
|
335
|
+
middlewareHandler.add(Middlewares.CircuitBreaker);
|
|
315
336
|
}
|
|
316
337
|
|
|
317
338
|
// timeout middleware
|
|
318
|
-
middlewareHandler.add(Middlewares.Timeout)
|
|
339
|
+
middlewareHandler.add(Middlewares.Timeout);
|
|
319
340
|
|
|
320
341
|
// Retry policy
|
|
321
342
|
if (options.retryPolicy.enabled) {
|
|
322
|
-
middlewareHandler.add(Middlewares.Retry)
|
|
343
|
+
middlewareHandler.add(Middlewares.Retry);
|
|
323
344
|
}
|
|
324
345
|
|
|
325
346
|
// Error handler
|
|
326
|
-
middlewareHandler.add(Middlewares.ErrorHandler)
|
|
347
|
+
middlewareHandler.add(Middlewares.ErrorHandler);
|
|
327
348
|
|
|
328
349
|
// Tracing
|
|
329
350
|
if (options.tracing.enabled) {
|
|
330
|
-
middlewareHandler.add(Middlewares.Tracing)
|
|
351
|
+
middlewareHandler.add(Middlewares.Tracing);
|
|
331
352
|
}
|
|
332
353
|
|
|
333
354
|
// Metrics
|
|
334
355
|
if (options.metrics.enabled) {
|
|
335
|
-
middlewareHandler.add(Middlewares.Metrics)
|
|
356
|
+
middlewareHandler.add(Middlewares.Metrics);
|
|
336
357
|
}
|
|
337
358
|
}
|
|
338
359
|
|
|
339
360
|
// Wrap runtime and broker methods for middlewares
|
|
340
|
-
runtime.actionInvoker.call = middlewareHandler.wrapMethod('call', runtime.actionInvoker.call)
|
|
341
|
-
runtime.actionInvoker.multiCall = middlewareHandler.wrapMethod('multiCall', broker.multiCall)
|
|
342
|
-
runtime.eventBus.emit = middlewareHandler.wrapMethod('emit', runtime.eventBus.emit)
|
|
343
|
-
runtime.eventBus.broadcast = middlewareHandler.wrapMethod('broadcast', runtime.eventBus.broadcast)
|
|
344
|
-
runtime.eventBus.broadcastLocal = middlewareHandler.wrapMethod('broadcastLocal', runtime.eventBus.broadcastLocal)
|
|
345
|
-
|
|
346
|
-
// Wrap
|
|
347
|
-
broker.createService = middlewareHandler.wrapMethod('createService', broker.createService)
|
|
348
|
-
broker.loadService = middlewareHandler.wrapMethod('loadService', broker.loadService)
|
|
349
|
-
broker.loadServices = middlewareHandler.wrapMethod('loadServices', broker.loadServices)
|
|
350
|
-
|
|
361
|
+
runtime.actionInvoker.call = middlewareHandler.wrapMethod('call', runtime.actionInvoker.call);
|
|
362
|
+
runtime.actionInvoker.multiCall = middlewareHandler.wrapMethod('multiCall', broker.multiCall);
|
|
363
|
+
runtime.eventBus.emit = middlewareHandler.wrapMethod('emit', runtime.eventBus.emit);
|
|
364
|
+
runtime.eventBus.broadcast = middlewareHandler.wrapMethod('broadcast', runtime.eventBus.broadcast);
|
|
365
|
+
runtime.eventBus.broadcastLocal = middlewareHandler.wrapMethod('broadcastLocal', runtime.eventBus.broadcastLocal);
|
|
366
|
+
|
|
367
|
+
// Wrap broker methods
|
|
368
|
+
broker.createService = middlewareHandler.wrapMethod('createService', broker.createService);
|
|
369
|
+
broker.loadService = middlewareHandler.wrapMethod('loadService', broker.loadService);
|
|
370
|
+
broker.loadServices = middlewareHandler.wrapMethod('loadServices', broker.loadServices);
|
|
371
|
+
broker.ping = middlewareHandler.wrapMethod('ping', broker.ping);
|
|
372
|
+
};
|
|
351
373
|
|
|
352
374
|
// Run "beforeRegisterMiddlewares" hook
|
|
353
375
|
if (isFunction(options.beforeRegisterMiddlewares)) {
|
|
354
|
-
options.beforeRegisterMiddlewares.call(broker, { broker, runtime })
|
|
376
|
+
options.beforeRegisterMiddlewares.call(broker, { broker, runtime });
|
|
355
377
|
}
|
|
356
378
|
|
|
357
379
|
// Register middlewares
|
|
358
|
-
registerMiddlewares(options.middlewares)
|
|
380
|
+
registerMiddlewares(options.middlewares);
|
|
359
381
|
|
|
360
382
|
// Stop the broker greaceful
|
|
361
383
|
/* istanbul ignore next */
|
|
362
384
|
const onClose = () => broker.stop()
|
|
363
385
|
.catch(error => broker.log.error(error))
|
|
364
|
-
.then(() => process.exit(0))
|
|
386
|
+
.then(() => process.exit(0));
|
|
365
387
|
|
|
366
388
|
// SIGTERM listener
|
|
367
|
-
process.setMaxListeners(0)
|
|
368
|
-
process.on('beforeExit', onClose)
|
|
369
|
-
process.on('exit', onClose)
|
|
370
|
-
process.on('SIGINT', onClose)
|
|
371
|
-
process.on('SIGTERM', onClose)
|
|
389
|
+
process.setMaxListeners(0);
|
|
390
|
+
process.on('beforeExit', onClose);
|
|
391
|
+
process.on('exit', onClose);
|
|
392
|
+
process.on('SIGINT', onClose);
|
|
393
|
+
process.on('SIGTERM', onClose);
|
|
372
394
|
|
|
373
395
|
// Add broker reference to runtime
|
|
374
|
-
Object.assign(runtime, { broker })
|
|
396
|
+
Object.assign(runtime, { broker });
|
|
375
397
|
|
|
376
398
|
// Call middleware hook for broker created.
|
|
377
|
-
middlewareHandler.callHandlersSync('created', [runtime])
|
|
399
|
+
middlewareHandler.callHandlersSync('created', [runtime]);
|
|
378
400
|
|
|
379
|
-
return broker
|
|
380
|
-
}
|
|
401
|
+
return broker;
|
|
402
|
+
};
|