@weave-js/core 0.9.4 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/ExtendableError.js +33 -0
- package/lib/broker/context.js +25 -13
- package/lib/broker/{default-options.js → defaultOptions.js} +25 -6
- package/lib/broker/index.js +224 -194
- package/lib/buildRuntime.js +70 -0
- package/lib/cache/adapters/base.js +143 -0
- package/lib/cache/adapters/inMemory.js +154 -0
- package/lib/cache/adapters/inMemoryLru.js +140 -0
- package/lib/cache/adapters/index.js +46 -0
- package/lib/cache/base.js +49 -44
- package/lib/cache/lock.js +21 -4
- package/lib/constants.js +8 -5
- package/lib/errorHandler.js +19 -0
- package/lib/errors.js +17 -10
- 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 +17 -92
- package/lib/logger/format/asHumanReadable.js +4 -3
- package/lib/logger/index.js +7 -1
- package/lib/logger/levels.js +8 -7
- package/lib/logger/tools.js +4 -0
- package/lib/logger/utils/format.js +18 -4
- package/lib/metrics/constants.js +8 -6
- package/lib/metrics/types/gauge.js +1 -1
- package/lib/middlewares/action-hooks/index.js +62 -14
- package/lib/middlewares/bulkhead/index.js +5 -4
- package/lib/middlewares/cache/index.js +106 -0
- package/lib/middlewares/circuit-breaker/index.js +41 -16
- package/lib/middlewares/context-tracker/index.js +3 -3
- package/lib/middlewares/error-handler/index.js +3 -3
- package/lib/middlewares/index.js +2 -1
- package/lib/middlewares/metrics/getMiddlewareWrapper.js +2 -2
- package/lib/middlewares/metrics/index.js +2 -2
- package/lib/middlewares/retry/index.js +11 -10
- package/lib/middlewares/timeout/index.js +5 -5
- package/lib/middlewares/tracing/index.js +27 -14
- package/lib/middlewares/tracing/tags.js +43 -0
- package/lib/middlewares/validator/index.js +6 -6
- package/lib/registry/{action-endpoint.js → actionEndpoint.js} +0 -0
- package/lib/registry/collections/{action-collection.js → actionCollection.js} +2 -2
- package/lib/registry/collections/{endpoint-collection.js → endpointCollection.js} +19 -3
- package/lib/registry/collections/{event-collection.js → eventCollection.js} +15 -9
- package/lib/registry/collections/{node-collection.js → nodeCollection.js} +1 -1
- package/lib/registry/collections/{service-collection.js → serviceCollection.js} +2 -2
- package/lib/registry/{event-endpoint.js → eventEndpoint.js} +1 -1
- package/lib/registry/node.js +1 -1
- package/lib/registry/registry.js +19 -38
- package/lib/registry/service/service.js +2 -2
- package/lib/registry/{service-item.js → serviceItem.js} +1 -1
- package/lib/runtime/{init-action-invoker.js → initActionInvoker.js} +3 -3
- package/lib/runtime/initCache.js +19 -0
- package/lib/runtime/{init-context-factory.js → initContextFactory.js} +2 -2
- package/lib/runtime/{init-eventbus.js → initEventbus.js} +11 -10
- 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} +1 -1
- package/lib/runtime/{init-registry.js → initRegistry.js} +1 -1
- 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} +1 -1
- 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} +16 -1
- package/lib/transport/adapters/adapters.js +1 -1
- package/lib/transport/adapters/dummy/index.js +3 -3
- package/lib/transport/adapters/index.js +1 -1
- 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 +215 -172
- package/lib/transport/errorPayloadFactory.js +18 -0
- package/lib/transport/{message-handlers.js → messageHandlers.js} +92 -23
- package/lib/transport/messageTypes.js +23 -0
- package/lib/types.js +86 -75
- package/lib/utils/index.js +1 -1
- 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 -1317
- package/lib/cache/index.js +0 -48
- package/lib/cache/memory.js +0 -91
- package/lib/middlewares/tracing/buildTags.js +0 -17
- package/lib/new-errors.js +0 -25
- package/lib/runtime/init-cache.js +0 -10
- 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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Author: Kevin Ries (kevin@fachw3rk.de)
|
|
3
3
|
* -----
|
|
4
|
-
* Copyright
|
|
4
|
+
* Copyright 2021 Fachwerk
|
|
5
5
|
*/
|
|
6
6
|
'use strict'
|
|
7
7
|
|
|
@@ -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 {
|
|
@@ -103,20 +113,22 @@ exports.createContext = (runtime) => {
|
|
|
103
113
|
* @returns {Context} New copied context
|
|
104
114
|
*/
|
|
105
115
|
copy () {
|
|
106
|
-
const
|
|
116
|
+
const contextCopy = exports.createContext(runtime)
|
|
107
117
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
+
contextCopy.nodeId = this.nodeId
|
|
119
|
+
contextCopy.options = this.options
|
|
120
|
+
contextCopy.data = this.data
|
|
121
|
+
contextCopy.meta = this.meta
|
|
122
|
+
contextCopy.parentContext = this.parentContext
|
|
123
|
+
contextCopy.callerNodeId = this.callerNodeId
|
|
124
|
+
contextCopy.requestId = this.requestId
|
|
125
|
+
contextCopy.tracing = this.tracing
|
|
126
|
+
contextCopy.level = this.level
|
|
127
|
+
contextCopy.eventName = this.eventName
|
|
128
|
+
contextCopy.eventType = this.eventType
|
|
129
|
+
contextCopy.eventGroups = this.eventGroups
|
|
118
130
|
|
|
119
|
-
return
|
|
131
|
+
return contextCopy
|
|
120
132
|
}
|
|
121
133
|
}
|
|
122
134
|
|
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
/*
|
|
6
6
|
* Author: Kevin Ries (kevin@fachw3rk.de)
|
|
7
7
|
* -----
|
|
8
|
-
* Copyright
|
|
8
|
+
* Copyright 2021 Fachwerk
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
/** @module weave */
|
|
12
12
|
const os = require('os')
|
|
13
|
+
const { createInMemoryCache } = require('../cache/adapters/inMemory.js')
|
|
13
14
|
const { loadBalancingStrategy } = require('../constants')
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -28,8 +29,11 @@ exports.getDefaultOptions = () => {
|
|
|
28
29
|
},
|
|
29
30
|
cache: {
|
|
30
31
|
enabled: false,
|
|
31
|
-
adapter:
|
|
32
|
-
ttl: 3000
|
|
32
|
+
adapter: createInMemoryCache(),
|
|
33
|
+
ttl: 3000,
|
|
34
|
+
lock: {
|
|
35
|
+
enabled: false
|
|
36
|
+
}
|
|
33
37
|
},
|
|
34
38
|
circuitBreaker: {
|
|
35
39
|
enabled: false,
|
|
@@ -49,7 +53,10 @@ exports.getDefaultOptions = () => {
|
|
|
49
53
|
heartbeatTimeout: 10 * 1000,
|
|
50
54
|
offlineNodeCheckInterval: 30 * 1000,
|
|
51
55
|
maxOfflineTime: 1000 * 60 * 10,
|
|
52
|
-
maxChunkSize: 256 * 1024
|
|
56
|
+
maxChunkSize: 256 * 1024,
|
|
57
|
+
streams: {
|
|
58
|
+
handleBackpressure: true
|
|
59
|
+
}
|
|
53
60
|
},
|
|
54
61
|
errorHandler: null,
|
|
55
62
|
loadInternalMiddlewares: true,
|
|
@@ -58,7 +65,7 @@ exports.getDefaultOptions = () => {
|
|
|
58
65
|
collectCommonMetrics: true,
|
|
59
66
|
collectInterval: 5000,
|
|
60
67
|
adapters: [],
|
|
61
|
-
defaultBuckets: [1, 5, 10, 20, 25, 30, 50, 100, 250, 500, 1000, 2500, 5000, 10000]
|
|
68
|
+
defaultBuckets: [1, 5, 10, 20, 25, 30, 40, 50, 100, 250, 500, 1000, 2500, 5000, 10000]
|
|
62
69
|
},
|
|
63
70
|
middlewares: null,
|
|
64
71
|
logger: {
|
|
@@ -72,7 +79,19 @@ exports.getDefaultOptions = () => {
|
|
|
72
79
|
tracing: {
|
|
73
80
|
enabled: false,
|
|
74
81
|
samplingRate: 1.0,
|
|
75
|
-
collectors: []
|
|
82
|
+
collectors: [],
|
|
83
|
+
actions: {
|
|
84
|
+
data: false,
|
|
85
|
+
tags: {}
|
|
86
|
+
},
|
|
87
|
+
events: {
|
|
88
|
+
data: false,
|
|
89
|
+
tags: {}
|
|
90
|
+
},
|
|
91
|
+
errors: {
|
|
92
|
+
fields: ['name', 'message', 'code', 'type', 'data'],
|
|
93
|
+
stackTrace: false
|
|
94
|
+
}
|
|
76
95
|
},
|
|
77
96
|
namespace: '',
|
|
78
97
|
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
|
/**
|
|
@@ -29,238 +29,268 @@ exports.createBrokerInstance = (runtime) => {
|
|
|
29
29
|
log,
|
|
30
30
|
services,
|
|
31
31
|
transport,
|
|
32
|
-
metrics
|
|
32
|
+
metrics,
|
|
33
|
+
cache
|
|
33
34
|
} = runtime
|
|
34
35
|
|
|
35
36
|
// Log Messages
|
|
36
37
|
log.info(`Initializing #weave node version ${version}`)
|
|
37
38
|
log.info(`Node Id: ${options.nodeId}`)
|
|
38
39
|
|
|
40
|
+
// Output namespace
|
|
39
41
|
if (options.namespace) {
|
|
40
42
|
log.info(`Namespace: ${options.namespace}`)
|
|
41
43
|
}
|
|
42
44
|
|
|
45
|
+
// Init metrics
|
|
43
46
|
if (metrics) {
|
|
44
47
|
metrics.init()
|
|
45
48
|
}
|
|
46
49
|
|
|
50
|
+
// Init cache
|
|
51
|
+
if (cache) {
|
|
52
|
+
cache.init()
|
|
53
|
+
}
|
|
54
|
+
|
|
47
55
|
// broker object
|
|
48
56
|
/** @type {Broker} */
|
|
49
|
-
const broker =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
broadcast: eventBus.broadcast.bind(this),
|
|
66
|
-
broadcastLocal: eventBus.broadcastLocal.bind(this),
|
|
67
|
-
call: runtime.actionInvoker.call.bind(this),
|
|
68
|
-
multiCall: runtime.actionInvoker.multiCall.bind(this),
|
|
69
|
-
waitForServices: services.waitForServices.bind(this),
|
|
70
|
-
createService: services.createService.bind(this),
|
|
71
|
-
/**
|
|
72
|
-
* Load and register a service from file.
|
|
73
|
-
* @param {string} fileName Path to the service file.
|
|
74
|
-
* @returns {Service} Service
|
|
75
|
-
*/
|
|
76
|
-
loadService (fileName) {
|
|
77
|
-
const filePath = path.resolve(fileName)
|
|
78
|
-
const schema = require(filePath)
|
|
79
|
-
const service = this.createService(schema)
|
|
80
|
-
|
|
81
|
-
// If the "watchSevrices" option is set - add service to service watcher.
|
|
82
|
-
if (options.watchServices) {
|
|
83
|
-
service.filename = fileName
|
|
84
|
-
services.watchService.call(this, service)
|
|
85
|
-
}
|
|
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
|
+
}
|
|
86
73
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
* Load services from a folder.
|
|
91
|
-
* @param {string} [folder='./services'] Path of the folder.
|
|
92
|
-
* @param {string} [fileMask='*.service.js'] Pattern of the service files
|
|
93
|
-
* @returns {number} Amount of services
|
|
94
|
-
*/
|
|
95
|
-
loadServices (folder = './services', fileMask = '*.service.js') {
|
|
96
|
-
const serviceFiles = glob.sync(path.join(folder, fileMask))
|
|
97
|
-
|
|
98
|
-
log.info(`Searching services in folder '${folder}' with name pattern '${fileMask}'.`)
|
|
99
|
-
log.info(`${serviceFiles.length} services found.`)
|
|
100
|
-
|
|
101
|
-
serviceFiles.forEach(fileName => this.loadService(fileName))
|
|
102
|
-
return serviceFiles.length
|
|
103
|
-
},
|
|
104
|
-
/**
|
|
105
|
-
* Starts the broker.
|
|
106
|
-
* @returns {Promise} Promise
|
|
107
|
-
*/
|
|
108
|
-
async start () {
|
|
109
|
-
const startTime = Date.now()
|
|
110
|
-
await middlewareHandler.callHandlersAsync('starting', [runtime], true)
|
|
111
|
-
|
|
112
|
-
if (transport) {
|
|
113
|
-
await transport.connect()
|
|
114
|
-
}
|
|
74
|
+
broker.getNextActionEndpoint = function (actionName, options = {}) {
|
|
75
|
+
return registry.getNextAvailableActionEndpoint(actionName, options)
|
|
76
|
+
}
|
|
115
77
|
|
|
116
|
-
|
|
117
|
-
await Promise.all(services.serviceList.map(service => service.start()))
|
|
118
|
-
} catch (error) {
|
|
119
|
-
log.error(error, 'Unable to start all services')
|
|
120
|
-
clearInterval(options.waitForServiceInterval)
|
|
121
|
-
throw error
|
|
122
|
-
}
|
|
78
|
+
broker.emit = eventBus.emit.bind(broker)
|
|
123
79
|
|
|
124
|
-
|
|
125
|
-
eventBus.broadcastLocal('$broker.started')
|
|
126
|
-
registry.generateLocalNodeInfo(true)
|
|
80
|
+
broker.broadcast = eventBus.broadcast.bind(broker)
|
|
127
81
|
|
|
128
|
-
|
|
129
|
-
await transport.setReady()
|
|
130
|
-
}
|
|
82
|
+
broker.broadcastLocal = eventBus.broadcastLocal.bind(broker)
|
|
131
83
|
|
|
132
|
-
|
|
84
|
+
broker.call = runtime.actionInvoker.call.bind(broker)
|
|
133
85
|
|
|
134
|
-
|
|
135
|
-
options.started.call(this)
|
|
136
|
-
}
|
|
86
|
+
broker.multiCall = runtime.actionInvoker.multiCall.bind(broker)
|
|
137
87
|
|
|
138
|
-
|
|
139
|
-
log.info(`Node "${options.nodeId}" with ${services.serviceList.length} services successfully started in ${duration}ms.`)
|
|
140
|
-
},
|
|
141
|
-
/**
|
|
142
|
-
* Stops the broker.
|
|
143
|
-
* @returns {Promise} Promise
|
|
144
|
-
*/
|
|
145
|
-
async stop () {
|
|
146
|
-
runtime.state.isStarted = false
|
|
147
|
-
log.info('Shutting down the node...')
|
|
148
|
-
|
|
149
|
-
await middlewareHandler.callHandlersAsync('stopping', [runtime], true)
|
|
150
|
-
|
|
151
|
-
try {
|
|
152
|
-
await Promise.all(services.serviceList.map(service => service.stop()))
|
|
153
|
-
} catch (error) {
|
|
154
|
-
log.error(error, 'Unable to stop all services.')
|
|
155
|
-
throw error
|
|
156
|
-
}
|
|
88
|
+
broker.waitForServices = services.waitForServices.bind(broker)
|
|
157
89
|
|
|
158
|
-
|
|
159
|
-
await transport.disconnect()
|
|
160
|
-
}
|
|
90
|
+
broker.createService = services.createService.bind(broker)
|
|
161
91
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Global error handler of the broker.
|
|
94
|
+
* @param {*} error Error
|
|
95
|
+
* @returns {void}
|
|
96
|
+
*/
|
|
97
|
+
broker.handleError = runtime.handleError
|
|
166
98
|
|
|
167
|
-
|
|
168
|
-
log.debug('Stopping metrics.')
|
|
169
|
-
await runtime.metrics.stop()
|
|
170
|
-
}
|
|
99
|
+
broker.fatalError = runtime.fatalError
|
|
171
100
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
+
}
|
|
176
116
|
|
|
177
|
-
|
|
117
|
+
return service
|
|
118
|
+
}
|
|
178
119
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
120
|
+
broker.loadServices = function (folder = './services', fileMask = '*.service.js') {
|
|
121
|
+
const serviceFiles = glob.sync(path.join(folder, fileMask))
|
|
182
122
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
eventBus.broadcastLocal('$broker.stopped')
|
|
186
|
-
|
|
187
|
-
process.removeListener('beforeExit', onClose)
|
|
188
|
-
process.removeListener('exit', onClose)
|
|
189
|
-
process.removeListener('SIGINT', onClose)
|
|
190
|
-
process.removeListener('SIGTERM', onClose)
|
|
191
|
-
|
|
192
|
-
// todo: handle errors
|
|
193
|
-
},
|
|
194
|
-
/**
|
|
195
|
-
* Send a ping to connected nodes.
|
|
196
|
-
* @param {*} nodeId Node id
|
|
197
|
-
* @param {number} [timeout=3000] Ping timeout
|
|
198
|
-
* @returns {Array} Ping result
|
|
199
|
-
*/
|
|
200
|
-
ping (nodeId, timeout = 3000) {
|
|
201
|
-
if (transport && transport.isConnected) {
|
|
202
|
-
if (nodeId) {
|
|
203
|
-
return new Promise((resolve) => {
|
|
204
|
-
const timeoutTimer = setTimeout(() => {
|
|
205
|
-
bus.off('$node.pong', pongHandler)
|
|
206
|
-
return resolve(null)
|
|
207
|
-
}, timeout)
|
|
123
|
+
log.info(`Searching services in folder '${folder}' with name pattern '${fileMask}'.`)
|
|
124
|
+
log.info(`${serviceFiles.length} services found.`)
|
|
208
125
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
resolve(pong)
|
|
213
|
-
}
|
|
126
|
+
serviceFiles.forEach(fileName => broker.loadService(fileName))
|
|
127
|
+
return serviceFiles.length
|
|
128
|
+
}
|
|
214
129
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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
|
+
}
|
|
221
150
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
151
|
+
runtime.state.isStarted = true
|
|
152
|
+
eventBus.broadcastLocal('$broker.started')
|
|
153
|
+
// refresh local node information
|
|
154
|
+
registry.generateLocalNodeInfo(true)
|
|
225
155
|
|
|
226
|
-
|
|
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
|
+
}
|
|
227
166
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
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
|
+
}
|
|
231
199
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
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
|
+
|
|
220
|
+
log.info('The node was successfully shut down. Bye bye! 👋')
|
|
221
|
+
|
|
222
|
+
eventBus.broadcastLocal('$broker.stopped')
|
|
223
|
+
|
|
224
|
+
process.removeListener('beforeExit', onClose)
|
|
225
|
+
process.removeListener('exit', onClose)
|
|
226
|
+
process.removeListener('SIGINT', onClose)
|
|
227
|
+
process.removeListener('SIGTERM', onClose)
|
|
228
|
+
|
|
229
|
+
// todo: handle errors
|
|
230
|
+
}
|
|
231
|
+
|
|
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.nodeCollection.list({})
|
|
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)
|
|
235
282
|
bus.off('$node.pong', pongHandler)
|
|
236
283
|
resolve(pongs)
|
|
237
|
-
}, timeout)
|
|
238
|
-
|
|
239
|
-
const pongHandler = pong => {
|
|
240
|
-
pongs[pong.nodeId] = pong
|
|
241
|
-
onFlight.delete(pong.nodeId)
|
|
242
|
-
if (onFlight.size === 0) {
|
|
243
|
-
clearTimeout(timeoutTimer)
|
|
244
|
-
bus.off('$node.pong', pongHandler)
|
|
245
|
-
resolve(pongs)
|
|
246
|
-
}
|
|
247
284
|
}
|
|
285
|
+
}
|
|
248
286
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
287
|
+
bus.on('$node.pong', pongHandler)
|
|
288
|
+
nodes.map(nodeId => transport.sendPing(nodeId))
|
|
289
|
+
})
|
|
253
290
|
}
|
|
291
|
+
}
|
|
254
292
|
|
|
255
|
-
|
|
256
|
-
},
|
|
257
|
-
/**
|
|
258
|
-
* Global error handler of the broker.
|
|
259
|
-
* @param {*} error Error
|
|
260
|
-
* @returns {void}
|
|
261
|
-
*/
|
|
262
|
-
handleError: runtime.handleError,
|
|
263
|
-
fatalError: runtime.fatalError
|
|
293
|
+
return Promise.resolve(nodeId ? null : {})
|
|
264
294
|
}
|
|
265
295
|
|
|
266
296
|
// Register internal broker events
|
|
@@ -296,7 +326,7 @@ exports.createBrokerInstance = (runtime) => {
|
|
|
296
326
|
|
|
297
327
|
// Cache
|
|
298
328
|
if (runtime.cache) {
|
|
299
|
-
middlewareHandler.add(
|
|
329
|
+
middlewareHandler.add(Middlewares.Cache)
|
|
300
330
|
}
|
|
301
331
|
|
|
302
332
|
// Context tracking
|
|
@@ -338,10 +368,11 @@ exports.createBrokerInstance = (runtime) => {
|
|
|
338
368
|
runtime.eventBus.broadcast = middlewareHandler.wrapMethod('broadcast', runtime.eventBus.broadcast)
|
|
339
369
|
runtime.eventBus.broadcastLocal = middlewareHandler.wrapMethod('broadcastLocal', runtime.eventBus.broadcastLocal)
|
|
340
370
|
|
|
341
|
-
// Wrap
|
|
371
|
+
// Wrap broker methods
|
|
342
372
|
broker.createService = middlewareHandler.wrapMethod('createService', broker.createService)
|
|
343
373
|
broker.loadService = middlewareHandler.wrapMethod('loadService', broker.loadService)
|
|
344
374
|
broker.loadServices = middlewareHandler.wrapMethod('loadServices', broker.loadServices)
|
|
375
|
+
broker.ping = middlewareHandler.wrapMethod('ping', broker.ping)
|
|
345
376
|
}
|
|
346
377
|
|
|
347
378
|
// Run "beforeRegisterMiddlewares" hook
|
|
@@ -373,4 +404,3 @@ exports.createBrokerInstance = (runtime) => {
|
|
|
373
404
|
|
|
374
405
|
return broker
|
|
375
406
|
}
|
|
376
|
-
|