@weave-js/core 0.10.0 → 0.11.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/lib/ExtendableError.js +33 -0
- package/lib/broker/context.js +12 -0
- package/lib/broker/{default-options.js → defaultOptions.js} +22 -4
- package/lib/broker/index.js +218 -192
- package/lib/{build-runtime.js → buildRuntime.js} +16 -16
- package/lib/cache/base.js +33 -28
- package/lib/cache/inMemory.js +140 -0
- package/lib/cache/index.js +1 -1
- package/lib/cache/lock.js +21 -4
- package/lib/constants.js +7 -4
- package/lib/{error-handler.js → errorHandler.js} +0 -0
- package/lib/errors.js +16 -9
- package/lib/helper/{define-action.js → defineAction.js} +3 -1
- package/lib/helper/{define-broker-options.js → defineBrokerOptions.js} +2 -0
- package/lib/helper/{define-service.js → defineService.js} +4 -1
- package/lib/index.js +13 -9
- package/lib/logger/format/asHumanReadable.js +4 -3
- package/lib/logger/index.js +4 -1
- package/lib/logger/levels.js +2 -1
- package/lib/logger/tools.js +4 -0
- package/lib/logger/utils/format.js +18 -4
- package/lib/metrics/constants.js +1 -1
- package/lib/metrics/types/gauge.js +1 -1
- package/lib/middlewares/action-hooks/index.js +59 -11
- package/lib/middlewares/bulkhead/index.js +2 -1
- package/lib/middlewares/cache/index.js +80 -0
- package/lib/middlewares/circuit-breaker/index.js +38 -13
- package/lib/middlewares/index.js +1 -0
- package/lib/middlewares/metrics/index.js +1 -1
- package/lib/middlewares/timeout/index.js +2 -2
- package/lib/middlewares/tracing/index.js +24 -11
- package/lib/middlewares/tracing/tags.js +43 -0
- package/lib/middlewares/validator/index.js +1 -1
- package/lib/registry/{action-endpoint.js → actionEndpoint.js} +0 -0
- package/lib/registry/collections/{action-collection.js → actionCollection.js} +1 -1
- package/lib/registry/collections/{endpoint-collection.js → endpointCollection.js} +2 -3
- package/lib/registry/collections/{event-collection.js → eventCollection.js} +4 -8
- package/lib/registry/collections/{node-collection.js → nodeCollection.js} +0 -0
- package/lib/registry/collections/{service-collection.js → serviceCollection.js} +1 -1
- package/lib/registry/{event-endpoint.js → eventEndpoint.js} +0 -0
- package/lib/registry/registry.js +9 -22
- package/lib/registry/service/service.js +2 -2
- package/lib/registry/{service-item.js → serviceItem.js} +0 -0
- package/lib/runtime/{init-action-invoker.js → initActionInvoker.js} +1 -1
- package/lib/runtime/{init-cache.js → initCache.js} +0 -0
- package/lib/runtime/{init-context-factory.js → initContextFactory.js} +0 -0
- package/lib/runtime/{init-eventbus.js → initEventbus.js} +8 -7
- package/lib/runtime/{init-logger.js → initLogger.js} +0 -0
- package/lib/runtime/{init-metrics.js → initMetrics.js} +11 -10
- package/lib/runtime/{init-middleware-manager.js → initMiddlewareManager.js} +0 -0
- package/lib/runtime/{init-registry.js → initRegistry.js} +0 -0
- package/lib/runtime/{init-service-manager.js → initServiceManager.js} +0 -0
- package/lib/runtime/{init-tracing.js → initTracing.js} +2 -1
- package/lib/runtime/{init-transport.js → initTransport.js} +0 -0
- package/lib/runtime/{init-uuid-factory.js → initUuidFactory.js} +0 -0
- package/lib/runtime/{init-validator.js → initValidator.js} +0 -0
- package/lib/tracing/collectors/base.js +11 -19
- package/lib/tracing/collectors/event.js +2 -2
- package/lib/tracing/collectors/index.js +2 -2
- package/lib/tracing/span.js +8 -6
- package/lib/transport/InboundTransformStream.js +75 -0
- package/lib/transport/adapters/{adapter-base.js → adapteBase.js} +15 -0
- package/lib/transport/adapters/adapters.js +1 -1
- package/lib/transport/adapters/dummy/index.js +2 -2
- package/lib/transport/adapters/tcp/discovery/index.js +45 -31
- package/lib/transport/adapters/tcp/index.js +20 -13
- package/lib/transport/adapters/tcp/tcpReader.js +1 -0
- package/lib/transport/adapters/tcp/tcpWriteStream.js +1 -1
- package/lib/transport/adapters/tcp/tcpWriter.js +2 -2
- package/lib/transport/createMessage.js +11 -0
- package/lib/transport/createTransport.js +214 -171
- package/lib/transport/errorPayloadFactory.js +18 -0
- package/lib/transport/{message-handlers.js → messageHandlers.js} +91 -22
- package/lib/transport/messageTypes.js +23 -0
- package/lib/types.js +49 -49
- package/lib/utils/options.js +4 -2
- package/lib/utils/{restore-error.js → restoreError.js} +1 -1
- package/package.json +6 -12
- package/CHANGELOG.md +0 -1334
- package/lib/cache/memory.js +0 -121
- package/lib/middlewares/tracing/buildTags.js +0 -17
- package/lib/new-errors.js +0 -25
- 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/message-types.js +0 -59
- package/lib/transport/message.js +0 -16
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
class ExtendableError extends Error {
|
|
2
|
+
constructor (message = '') {
|
|
3
|
+
super(message)
|
|
4
|
+
|
|
5
|
+
Object.defineProperty(this, 'name', {
|
|
6
|
+
configurable: true,
|
|
7
|
+
enumerable: false,
|
|
8
|
+
value: this.constructor.name,
|
|
9
|
+
writable: true
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
Object.defineProperty(this, 'message', {
|
|
13
|
+
configurable: true,
|
|
14
|
+
enumerable: false,
|
|
15
|
+
value: message,
|
|
16
|
+
writable: true
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
if (Object.prototype.hasOwnProperty.call(Error, 'captureStackTrace')) {
|
|
20
|
+
Error.captureStackTrace(this, this.constructor)
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
Object.defineProperty(this, 'stack', {
|
|
25
|
+
configurable: true,
|
|
26
|
+
enumerable: false,
|
|
27
|
+
value: new Error(message).stack,
|
|
28
|
+
writable: true
|
|
29
|
+
})
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = { ExtendableError }
|
package/lib/broker/context.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @typedef {import('../types').Context} Context
|
|
10
10
|
* @typedef {import('../types').Runtime} Runtime
|
|
11
11
|
* @typedef {import('../types').ContextPromise} ContextPromise
|
|
12
|
+
* @typedef {import('../types').Endpoint} Endpoint
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
const { uuid, isFunction, isStream, isStreamObjectMode } = require('@weave-js/utils')
|
|
@@ -85,6 +86,15 @@ exports.createContext = (runtime) => {
|
|
|
85
86
|
})
|
|
86
87
|
},
|
|
87
88
|
startSpan (name, options) {
|
|
89
|
+
options = Object.assign({
|
|
90
|
+
id: this.id,
|
|
91
|
+
traceId: this.requestId,
|
|
92
|
+
parentId: this.parentId,
|
|
93
|
+
type: 'action',
|
|
94
|
+
service: this.service,
|
|
95
|
+
sampled: this.tracing
|
|
96
|
+
}, options)
|
|
97
|
+
|
|
88
98
|
if (this.span) {
|
|
89
99
|
this.span = this.span.startChildSpan(name, options)
|
|
90
100
|
} else {
|
|
@@ -111,6 +121,8 @@ exports.createContext = (runtime) => {
|
|
|
111
121
|
contextCopy.meta = this.meta
|
|
112
122
|
contextCopy.parentContext = this.parentContext
|
|
113
123
|
contextCopy.callerNodeId = this.callerNodeId
|
|
124
|
+
contextCopy.requestId = this.requestId
|
|
125
|
+
contextCopy.tracing = this.tracing
|
|
114
126
|
contextCopy.level = this.level
|
|
115
127
|
contextCopy.eventName = this.eventName
|
|
116
128
|
contextCopy.eventType = this.eventType
|
|
@@ -29,7 +29,10 @@ exports.getDefaultOptions = () => {
|
|
|
29
29
|
cache: {
|
|
30
30
|
enabled: false,
|
|
31
31
|
adapter: 'memory',
|
|
32
|
-
ttl: 3000
|
|
32
|
+
ttl: 3000,
|
|
33
|
+
lock: {
|
|
34
|
+
enabled: false
|
|
35
|
+
}
|
|
33
36
|
},
|
|
34
37
|
circuitBreaker: {
|
|
35
38
|
enabled: false,
|
|
@@ -49,7 +52,10 @@ exports.getDefaultOptions = () => {
|
|
|
49
52
|
heartbeatTimeout: 10 * 1000,
|
|
50
53
|
offlineNodeCheckInterval: 30 * 1000,
|
|
51
54
|
maxOfflineTime: 1000 * 60 * 10,
|
|
52
|
-
maxChunkSize: 256 * 1024
|
|
55
|
+
maxChunkSize: 256 * 1024,
|
|
56
|
+
streams: {
|
|
57
|
+
handleBackpressure: true
|
|
58
|
+
}
|
|
53
59
|
},
|
|
54
60
|
errorHandler: null,
|
|
55
61
|
loadInternalMiddlewares: true,
|
|
@@ -58,7 +64,7 @@ exports.getDefaultOptions = () => {
|
|
|
58
64
|
collectCommonMetrics: true,
|
|
59
65
|
collectInterval: 5000,
|
|
60
66
|
adapters: [],
|
|
61
|
-
defaultBuckets: [1, 5, 10, 20, 25, 30, 50, 100, 250, 500, 1000, 2500, 5000, 10000]
|
|
67
|
+
defaultBuckets: [1, 5, 10, 20, 25, 30, 40, 50, 100, 250, 500, 1000, 2500, 5000, 10000]
|
|
62
68
|
},
|
|
63
69
|
middlewares: null,
|
|
64
70
|
logger: {
|
|
@@ -72,7 +78,19 @@ exports.getDefaultOptions = () => {
|
|
|
72
78
|
tracing: {
|
|
73
79
|
enabled: false,
|
|
74
80
|
samplingRate: 1.0,
|
|
75
|
-
collectors: []
|
|
81
|
+
collectors: [],
|
|
82
|
+
actions: {
|
|
83
|
+
data: false,
|
|
84
|
+
tags: {}
|
|
85
|
+
},
|
|
86
|
+
events: {
|
|
87
|
+
data: false,
|
|
88
|
+
tags: {}
|
|
89
|
+
},
|
|
90
|
+
errors: {
|
|
91
|
+
fields: ['name', 'message', 'code', 'type', 'data'],
|
|
92
|
+
stackTrace: false
|
|
93
|
+
}
|
|
76
94
|
},
|
|
77
95
|
namespace: '',
|
|
78
96
|
registry: {
|
package/lib/broker/index.js
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
// node packages
|
|
9
|
+
const { isFunction } = require('@weave-js/utils')
|
|
9
10
|
const path = require('path')
|
|
10
11
|
const glob = require('glob')
|
|
11
|
-
const { isFunction } = require('@weave-js/utils')
|
|
12
12
|
const Middlewares = require('../middlewares')
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -37,235 +37,260 @@ exports.createBrokerInstance = (runtime) => {
|
|
|
37
37
|
log.info(`Initializing #weave node version ${version}`)
|
|
38
38
|
log.info(`Node Id: ${options.nodeId}`)
|
|
39
39
|
|
|
40
|
+
// Output namespace
|
|
40
41
|
if (options.namespace) {
|
|
41
42
|
log.info(`Namespace: ${options.namespace}`)
|
|
42
43
|
}
|
|
43
44
|
|
|
45
|
+
// Init metrics
|
|
44
46
|
if (metrics) {
|
|
45
47
|
metrics.init()
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
// Init cache
|
|
48
51
|
if (cache) {
|
|
49
52
|
cache.init()
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
// broker object
|
|
53
56
|
/** @type {Broker} */
|
|
54
|
-
const broker =
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
}
|
|
57
|
+
const broker = Object.create(null)
|
|
58
|
+
|
|
59
|
+
broker.runtime = runtime
|
|
60
|
+
broker.registry = registry
|
|
61
|
+
broker.bus = bus
|
|
62
|
+
broker.nodeId = options.nodeId
|
|
63
|
+
broker.version = version
|
|
64
|
+
broker.options = options
|
|
65
|
+
broker.validator = validator
|
|
66
|
+
broker.contextFactory = contextFactory
|
|
67
|
+
broker.log = log
|
|
68
|
+
broker.createLogger = runtime.createLogger
|
|
69
|
+
|
|
70
|
+
broker.getUUID = function () {
|
|
71
|
+
return runtime.generateUUID()
|
|
72
|
+
}
|
|
91
73
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
* Load services from a folder.
|
|
96
|
-
* @param {string} [folder='./services'] Path of the folder.
|
|
97
|
-
* @param {string} [fileMask='*.service.js'] Pattern of the service files
|
|
98
|
-
* @returns {number} Amount of services
|
|
99
|
-
*/
|
|
100
|
-
loadServices (folder = './services', fileMask = '*.service.js') {
|
|
101
|
-
const serviceFiles = glob.sync(path.join(folder, fileMask))
|
|
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
|
-
}
|
|
74
|
+
broker.getNextActionEndpoint = function (actionName, options = {}) {
|
|
75
|
+
return registry.getNextAvailableActionEndpoint(actionName, options)
|
|
76
|
+
}
|
|
120
77
|
|
|
121
|
-
|
|
122
|
-
await Promise.all(services.serviceList.map(service => service.start()))
|
|
123
|
-
} catch (error) {
|
|
124
|
-
log.error(error, 'Unable to start all services')
|
|
125
|
-
clearInterval(options.waitForServiceInterval)
|
|
126
|
-
throw error
|
|
127
|
-
}
|
|
78
|
+
broker.emit = eventBus.emit.bind(broker)
|
|
128
79
|
|
|
129
|
-
|
|
130
|
-
eventBus.broadcastLocal('$broker.started')
|
|
131
|
-
registry.generateLocalNodeInfo(true)
|
|
80
|
+
broker.broadcast = eventBus.broadcast.bind(broker)
|
|
132
81
|
|
|
133
|
-
|
|
134
|
-
await transport.setReady()
|
|
135
|
-
}
|
|
82
|
+
broker.broadcastLocal = eventBus.broadcastLocal.bind(broker)
|
|
136
83
|
|
|
137
|
-
|
|
84
|
+
broker.call = runtime.actionInvoker.call.bind(broker)
|
|
138
85
|
|
|
139
|
-
|
|
140
|
-
options.started.call(this)
|
|
141
|
-
}
|
|
86
|
+
broker.multiCall = runtime.actionInvoker.multiCall.bind(broker)
|
|
142
87
|
|
|
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
|
-
}
|
|
88
|
+
broker.waitForServices = services.waitForServices.bind(broker)
|
|
162
89
|
|
|
163
|
-
|
|
164
|
-
await transport.disconnect()
|
|
165
|
-
}
|
|
90
|
+
broker.createService = services.createService.bind(broker)
|
|
166
91
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Global error handler of the broker.
|
|
94
|
+
* @param {*} error Error
|
|
95
|
+
* @returns {void}
|
|
96
|
+
*/
|
|
97
|
+
broker.handleError = runtime.handleError
|
|
171
98
|
|
|
172
|
-
|
|
173
|
-
log.debug('Stopping metrics.')
|
|
174
|
-
await runtime.metrics.stop()
|
|
175
|
-
}
|
|
99
|
+
broker.fatalError = runtime.fatalError
|
|
176
100
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Load and register a service from file.
|
|
103
|
+
* @param {string} fileName Path to the service file.
|
|
104
|
+
* @returns {Service} Service
|
|
105
|
+
*/
|
|
106
|
+
broker.loadService = function (fileName) {
|
|
107
|
+
const filePath = path.resolve(fileName)
|
|
108
|
+
const schema = require(filePath)
|
|
109
|
+
const service = broker.createService(schema)
|
|
110
|
+
|
|
111
|
+
// If the "watchSevrices" option is set - add service to service watcher.
|
|
112
|
+
if (options.watchServices) {
|
|
113
|
+
service.filename = fileName
|
|
114
|
+
services.watchService.call(broker, service)
|
|
115
|
+
}
|
|
181
116
|
|
|
182
|
-
|
|
117
|
+
return service
|
|
118
|
+
}
|
|
183
119
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
120
|
+
broker.loadServices = function (folder = './services', fileMask = '*.service.js') {
|
|
121
|
+
const serviceFiles = glob.sync(path.join(folder, fileMask))
|
|
187
122
|
|
|
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)
|
|
123
|
+
log.info(`Searching services in folder '${folder}' with name pattern '${fileMask}'.`)
|
|
124
|
+
log.info(`${serviceFiles.length} services found.`)
|
|
213
125
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
126
|
+
serviceFiles.forEach(fileName => broker.loadService(fileName))
|
|
127
|
+
return serviceFiles.length
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Starts the broker.
|
|
132
|
+
* @returns {Promise} Promise
|
|
133
|
+
*/
|
|
134
|
+
broker.start = async function () {
|
|
135
|
+
const startTime = Date.now()
|
|
136
|
+
await middlewareHandler.callHandlersAsync('starting', [runtime], true)
|
|
137
|
+
|
|
138
|
+
// If transport is used, we connect the transport adapter.
|
|
139
|
+
if (transport) {
|
|
140
|
+
await transport.connect()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
try {
|
|
144
|
+
await Promise.all(services.serviceList.map(service => service.start()))
|
|
145
|
+
} catch (error) {
|
|
146
|
+
log.error(error, 'Unable to start all services')
|
|
147
|
+
clearInterval(options.waitForServiceInterval)
|
|
148
|
+
throw error
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
runtime.state.isStarted = true
|
|
152
|
+
eventBus.broadcastLocal('$broker.started')
|
|
153
|
+
// refresh local node information
|
|
154
|
+
registry.generateLocalNodeInfo(true)
|
|
155
|
+
|
|
156
|
+
// If transport is used, we set the transport ready to inform the other nodes
|
|
157
|
+
if (transport) {
|
|
158
|
+
await transport.setReady()
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
await middlewareHandler.callHandlersAsync('started', [runtime], true)
|
|
162
|
+
|
|
163
|
+
if (runtime.state.isStarted && isFunction(options.started)) {
|
|
164
|
+
options.started.call(broker)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const duration = Date.now() - startTime
|
|
168
|
+
log.info(`Node "${options.nodeId}" with ${services.serviceList.length} services successfully started in ${duration}ms.`)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Stops the broker.
|
|
173
|
+
* @returns {Promise} Promise
|
|
174
|
+
*/
|
|
175
|
+
broker.stop = async function () {
|
|
176
|
+
runtime.state.isStarted = false
|
|
177
|
+
log.info('Shutting down the node...')
|
|
178
|
+
|
|
179
|
+
await middlewareHandler.callHandlersAsync('stopping', [runtime], true)
|
|
180
|
+
|
|
181
|
+
// Stop services
|
|
182
|
+
try {
|
|
183
|
+
await Promise.all(services.serviceList.map(service => service.stop()))
|
|
184
|
+
} catch (error) {
|
|
185
|
+
log.error(error, 'Unable to stop all services.')
|
|
186
|
+
throw error
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Disconnect transports
|
|
190
|
+
if (transport) {
|
|
191
|
+
await transport.disconnect()
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Stop cache
|
|
195
|
+
if (runtime.cache) {
|
|
196
|
+
log.debug('Stopping caching adapters.')
|
|
197
|
+
await runtime.cache.stop()
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Stop metrics
|
|
201
|
+
if (runtime.metrics) {
|
|
202
|
+
log.debug('Stopping metrics.')
|
|
203
|
+
await runtime.metrics.stop()
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Stop tracers
|
|
207
|
+
if (runtime.tracer) {
|
|
208
|
+
log.debug('Stopping tracing adapters.')
|
|
209
|
+
await runtime.tracer.stop()
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Call "stopped" middleware method.
|
|
213
|
+
await middlewareHandler.callHandlersAsync('stopped', [runtime], true)
|
|
214
|
+
|
|
215
|
+
// Call "stopped" lifecycle hook
|
|
216
|
+
if (!runtime.state.isStarted && isFunction(options.stopped)) {
|
|
217
|
+
options.stopped.call(runtime)
|
|
218
|
+
}
|
|
219
219
|
|
|
220
|
-
|
|
221
|
-
transport.sendPing(nodeId)
|
|
222
|
-
})
|
|
223
|
-
} else {
|
|
224
|
-
// handle arrays
|
|
225
|
-
const pongs = {}
|
|
220
|
+
log.info('The node was successfully shut down. Bye bye! 👋')
|
|
226
221
|
|
|
227
|
-
|
|
228
|
-
.filter(node => !node.isLocal)
|
|
229
|
-
.map(node => node.id)
|
|
222
|
+
eventBus.broadcastLocal('$broker.stopped')
|
|
230
223
|
|
|
231
|
-
|
|
224
|
+
process.removeListener('beforeExit', onClose)
|
|
225
|
+
process.removeListener('exit', onClose)
|
|
226
|
+
process.removeListener('SIGINT', onClose)
|
|
227
|
+
process.removeListener('SIGTERM', onClose)
|
|
232
228
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
})
|
|
229
|
+
// todo: handle errors
|
|
230
|
+
}
|
|
236
231
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
232
|
+
/**
|
|
233
|
+
* Ping other nodes
|
|
234
|
+
* @param {string=} nodeId Node ID
|
|
235
|
+
* @param {number} timeout Timeout
|
|
236
|
+
* @returns {Object<string, number>} Result
|
|
237
|
+
*/
|
|
238
|
+
broker.ping = function (nodeId, timeout = 3000) {
|
|
239
|
+
if (transport && transport.isConnected) {
|
|
240
|
+
if (nodeId) {
|
|
241
|
+
return new Promise((resolve) => {
|
|
242
|
+
const timeoutTimer = setTimeout(() => {
|
|
243
|
+
bus.off('$node.pong', pongHandler)
|
|
244
|
+
return resolve(null)
|
|
245
|
+
}, timeout)
|
|
246
|
+
|
|
247
|
+
const pongHandler = pong => {
|
|
248
|
+
clearTimeout(timeoutTimer)
|
|
249
|
+
bus.off('$node.pong', pongHandler)
|
|
250
|
+
resolve(pong)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
bus.on('$node.pong', pongHandler)
|
|
254
|
+
transport.sendPing(nodeId)
|
|
255
|
+
})
|
|
256
|
+
} else {
|
|
257
|
+
// handle arrays
|
|
258
|
+
const pongs = {}
|
|
259
|
+
|
|
260
|
+
const nodes = registry.getNodeList({})
|
|
261
|
+
.filter(node => !node.isLocal)
|
|
262
|
+
.map(node => node.id)
|
|
263
|
+
|
|
264
|
+
const onFlight = new Set(nodes)
|
|
265
|
+
|
|
266
|
+
nodes.forEach(nodeId => {
|
|
267
|
+
pongs[nodeId] = null
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
return new Promise((resolve) => {
|
|
271
|
+
// todo: handle timeout
|
|
272
|
+
const timeoutTimer = setTimeout(() => {
|
|
273
|
+
bus.off('$node.pong', pongHandler)
|
|
274
|
+
resolve(pongs)
|
|
275
|
+
}, timeout)
|
|
276
|
+
|
|
277
|
+
const pongHandler = pong => {
|
|
278
|
+
pongs[pong.nodeId] = pong
|
|
279
|
+
onFlight.delete(pong.nodeId)
|
|
280
|
+
if (onFlight.size === 0) {
|
|
281
|
+
clearTimeout(timeoutTimer)
|
|
240
282
|
bus.off('$node.pong', pongHandler)
|
|
241
283
|
resolve(pongs)
|
|
242
|
-
}, timeout)
|
|
243
|
-
|
|
244
|
-
const pongHandler = pong => {
|
|
245
|
-
pongs[pong.nodeId] = pong
|
|
246
|
-
onFlight.delete(pong.nodeId)
|
|
247
|
-
if (onFlight.size === 0) {
|
|
248
|
-
clearTimeout(timeoutTimer)
|
|
249
|
-
bus.off('$node.pong', pongHandler)
|
|
250
|
-
resolve(pongs)
|
|
251
|
-
}
|
|
252
284
|
}
|
|
285
|
+
}
|
|
253
286
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
}
|
|
287
|
+
bus.on('$node.pong', pongHandler)
|
|
288
|
+
nodes.map(nodeId => transport.sendPing(nodeId))
|
|
289
|
+
})
|
|
258
290
|
}
|
|
291
|
+
}
|
|
259
292
|
|
|
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
|
|
293
|
+
return Promise.resolve(nodeId ? null : {})
|
|
269
294
|
}
|
|
270
295
|
|
|
271
296
|
// Register internal broker events
|
|
@@ -301,7 +326,7 @@ exports.createBrokerInstance = (runtime) => {
|
|
|
301
326
|
|
|
302
327
|
// Cache
|
|
303
328
|
if (runtime.cache) {
|
|
304
|
-
middlewareHandler.add(
|
|
329
|
+
middlewareHandler.add(Middlewares.Cache)
|
|
305
330
|
}
|
|
306
331
|
|
|
307
332
|
// Context tracking
|
|
@@ -343,10 +368,11 @@ exports.createBrokerInstance = (runtime) => {
|
|
|
343
368
|
runtime.eventBus.broadcast = middlewareHandler.wrapMethod('broadcast', runtime.eventBus.broadcast)
|
|
344
369
|
runtime.eventBus.broadcastLocal = middlewareHandler.wrapMethod('broadcastLocal', runtime.eventBus.broadcastLocal)
|
|
345
370
|
|
|
346
|
-
// Wrap
|
|
371
|
+
// Wrap broker methods
|
|
347
372
|
broker.createService = middlewareHandler.wrapMethod('createService', broker.createService)
|
|
348
373
|
broker.loadService = middlewareHandler.wrapMethod('loadService', broker.loadService)
|
|
349
374
|
broker.loadServices = middlewareHandler.wrapMethod('loadServices', broker.loadServices)
|
|
375
|
+
broker.ping = middlewareHandler.wrapMethod('ping', broker.ping)
|
|
350
376
|
}
|
|
351
377
|
|
|
352
378
|
// Run "beforeRegisterMiddlewares" hook
|
|
@@ -4,30 +4,30 @@
|
|
|
4
4
|
* @typedef {import('./types.js').Broker} Broker
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const { initLogger } = require('./runtime/
|
|
8
|
-
const { initMiddlewareHandler } = require('./runtime/
|
|
9
|
-
const { initRegistry } = require('./runtime/
|
|
10
|
-
const { initContextFactory } = require('./runtime/
|
|
11
|
-
const { initEventbus } = require('./runtime/
|
|
12
|
-
const { initValidator } = require('./runtime/
|
|
13
|
-
const { initTransport } = require('./runtime/
|
|
14
|
-
const { initCache } = require('./runtime/
|
|
15
|
-
const { initActionInvoker } = require('./runtime/
|
|
16
|
-
const { initServiceManager } = require('./runtime/
|
|
17
|
-
const { initMetrics } = require('./runtime/
|
|
18
|
-
const { initTracer } = require('./runtime/
|
|
19
|
-
const { initUUIDFactory } = require('./runtime/
|
|
7
|
+
const { initLogger } = require('./runtime/initLogger')
|
|
8
|
+
const { initMiddlewareHandler } = require('./runtime/initMiddlewareManager')
|
|
9
|
+
const { initRegistry } = require('./runtime/initRegistry')
|
|
10
|
+
const { initContextFactory } = require('./runtime/initContextFactory')
|
|
11
|
+
const { initEventbus } = require('./runtime/initEventbus')
|
|
12
|
+
const { initValidator } = require('./runtime/initValidator')
|
|
13
|
+
const { initTransport } = require('./runtime/initTransport')
|
|
14
|
+
const { initCache } = require('./runtime/initCache')
|
|
15
|
+
const { initActionInvoker } = require('./runtime/initActionInvoker')
|
|
16
|
+
const { initServiceManager } = require('./runtime/initServiceManager')
|
|
17
|
+
const { initMetrics } = require('./runtime/initMetrics')
|
|
18
|
+
const { initTracer } = require('./runtime/initTracing')
|
|
19
|
+
const { initUUIDFactory } = require('./runtime/initUuidFactory')
|
|
20
|
+
const { errorHandler, fatalErrorHandler } = require('./errorHandler')
|
|
21
|
+
const { uuid } = require('@weave-js/utils')
|
|
20
22
|
const { version } = require('../package.json')
|
|
21
|
-
const { errorHandler, fatalErrorHandler } = require('./error-handler')
|
|
22
23
|
const EventEmitter = require('eventemitter2')
|
|
23
|
-
const { uuid } = require('@weave-js/utils')
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* Build runtime object
|
|
27
27
|
* @param {BrokerOptions} options Broker options
|
|
28
28
|
* @return {Runtime} Runtime
|
|
29
29
|
*/
|
|
30
|
-
exports.
|
|
30
|
+
exports.initRuntime = (options) => {
|
|
31
31
|
/**
|
|
32
32
|
* Event bus
|
|
33
33
|
* @returns {EventEmitter} Service object.
|