@weave-js/core 0.9.2 → 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 +25 -13
- package/lib/broker/{default-options.js → defaultOptions.js} +23 -5
- package/lib/broker/index.js +224 -194
- package/lib/buildRuntime.js +70 -0
- package/lib/cache/base.js +47 -31
- package/lib/cache/inMemory.js +140 -0
- package/lib/cache/index.js +2 -2
- 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 +15 -89
- package/lib/logger/base.js +3 -3
- package/lib/logger/format/asHumanReadable.js +42 -0
- package/lib/logger/format/asJson.js +25 -0
- package/lib/logger/format/index.js +4 -0
- package/lib/logger/index.js +12 -5
- package/lib/logger/levels.js +9 -8
- package/lib/logger/tools.js +4 -25
- package/lib/logger/utils/colorize.js +32 -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 +80 -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 +10 -23
- 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/{init-cache.js → initCache.js} +0 -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} +1 -1
- 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/{transport-factory.js → createTransport.js} +234 -173
- package/lib/transport/errorPayloadFactory.js +18 -0
- package/lib/transport/{message-handlers.js → messageHandlers.js} +93 -24
- package/lib/transport/messageTypes.js +23 -0
- package/lib/types.js +66 -66
- package/lib/utils/index.js +0 -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 -1293
- package/lib/cache/memory.js +0 -91
- 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
|
@@ -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
|
|
|
7
7
|
/**
|
|
@@ -9,13 +9,16 @@
|
|
|
9
9
|
* @typedef {import('../types.js').TransportAdapter} TransportAdapter
|
|
10
10
|
* @typedef {import('../types.js').Transport} Transport
|
|
11
11
|
* @typedef {import('../types').TransportMessage} TransportMessage
|
|
12
|
+
* @typedef {import('../types').Context} Context
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
// Own packages
|
|
15
16
|
const { WeaveError, WeaveQueueSizeExceededError } = require('../errors')
|
|
16
|
-
const
|
|
17
|
+
const { createMessage } = require('./createMessage')
|
|
18
|
+
const MessageTypes = require('./messageTypes')
|
|
17
19
|
const utils = require('@weave-js/utils')
|
|
18
|
-
const createMessageHandler = require('./
|
|
20
|
+
const createMessageHandler = require('./messageHandlers')
|
|
21
|
+
const { errorPayloadFactory } = require('./errorPayloadFactory')
|
|
19
22
|
|
|
20
23
|
/**
|
|
21
24
|
* Create a Transport adapter
|
|
@@ -25,139 +28,30 @@ const createMessageHandler = require('./message-handlers')
|
|
|
25
28
|
*/
|
|
26
29
|
exports.createTransport = (runtime, adapter) => {
|
|
27
30
|
const transport = Object.create(null)
|
|
28
|
-
const { nodeId, middlewareHandler } = runtime
|
|
31
|
+
const { nodeId, middlewareHandler, createLogger } = runtime
|
|
29
32
|
|
|
30
33
|
let heartbeatTimer
|
|
31
34
|
let checkNodesTimer
|
|
32
35
|
let checkOfflineNodesTimer
|
|
33
36
|
let updateLocalNodeTimer
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
|
|
38
|
+
// Pending action store
|
|
37
39
|
const pending = {
|
|
38
40
|
requests: new Map(),
|
|
39
41
|
requestStreams: new Map(),
|
|
40
|
-
responseStreams: new Map()
|
|
42
|
+
responseStreams: new Map(),
|
|
43
|
+
outboundResponseStreams: new Map(),
|
|
44
|
+
outboundRequestStreams: new Map()
|
|
41
45
|
}
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const isStream = utils.isStream(context.options.stream)
|
|
46
|
-
|
|
47
|
-
const request = {
|
|
48
|
-
targetNodeId: context.nodeId,
|
|
49
|
-
action: context.action.name,
|
|
50
|
-
context,
|
|
51
|
-
resolve,
|
|
52
|
-
reject,
|
|
53
|
-
isStream
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
log.debug(`Send request for ${request.action} to node ${request.targetNodeId}.`)
|
|
57
|
-
|
|
58
|
-
pending.requests.set(context.id, request)
|
|
59
|
-
|
|
60
|
-
const payload = {
|
|
61
|
-
id: context.id,
|
|
62
|
-
action: context.action.name,
|
|
63
|
-
data: context.data,
|
|
64
|
-
timeout: context.options.timeout,
|
|
65
|
-
meta: context.meta,
|
|
66
|
-
level: context.level,
|
|
67
|
-
metrics: context.metrics,
|
|
68
|
-
requestId: context.requestId,
|
|
69
|
-
parentId: context.parentId,
|
|
70
|
-
isStream
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Handle object mode streams
|
|
74
|
-
if (isStream) {
|
|
75
|
-
if (utils.isStreamObjectMode(context.options.stream)) {
|
|
76
|
-
payload.meta = payload.meta || {}
|
|
77
|
-
payload.meta.$isObjectModeStream = true
|
|
78
|
-
}
|
|
79
|
-
payload.sequence = 0
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const message = transport.createMessage(MessageTypes.MESSAGE_REQUEST, context.nodeId, payload)
|
|
83
|
-
|
|
84
|
-
return transport.send(message)
|
|
85
|
-
.then(() => {
|
|
86
|
-
// send stream
|
|
87
|
-
if (isStream) {
|
|
88
|
-
const stream = context.options.stream
|
|
89
|
-
payload.meta = {}
|
|
90
|
-
|
|
91
|
-
if (utils.isStreamObjectMode(context.options.stream)) {
|
|
92
|
-
payload.meta.$isObjectModeStream = true
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
stream.on('data', data => {
|
|
96
|
-
stream.pause()
|
|
97
|
-
const chunks = []
|
|
98
|
-
|
|
99
|
-
// The chunk is larger than maxBufferSize
|
|
100
|
-
if (data instanceof Buffer && runtime.options.transport.maxChunkSize > 0 && data.length > runtime.options.transport.maxChunkSize) {
|
|
101
|
-
const length = data.length
|
|
102
|
-
let i = 0
|
|
103
|
-
while (i < length) {
|
|
104
|
-
chunks.push(data.slice(i, i += runtime.options.transport.maxChunkSize))
|
|
105
|
-
}
|
|
106
|
-
} else {
|
|
107
|
-
chunks.push(data)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// Send chunks from chunk buffer
|
|
111
|
-
for (const chunk of chunks) {
|
|
112
|
-
const payloadCopy = Object.assign({}, payload)
|
|
113
|
-
payloadCopy.sequence = ++payload.sequence
|
|
114
|
-
payloadCopy.chunk = chunk
|
|
115
|
-
payloadCopy.isStream = true
|
|
116
|
-
payload.data = null
|
|
117
|
-
|
|
118
|
-
const message = transport.createMessage(MessageTypes.MESSAGE_REQUEST, context.nodeId, payloadCopy)
|
|
119
|
-
transport.send(message)
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// resume stream
|
|
123
|
-
stream.resume()
|
|
124
|
-
return
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
stream.on('end', () => {
|
|
128
|
-
const payloadCopy = Object.assign({}, payload)
|
|
129
|
-
payloadCopy.sequence = ++payload.sequence
|
|
130
|
-
payloadCopy.chunk = null
|
|
131
|
-
payloadCopy.isStream = false
|
|
132
|
-
const message = transport.createMessage(MessageTypes.MESSAGE_REQUEST, context.nodeId, payloadCopy)
|
|
133
|
-
return transport.send(message)
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
stream.on('error', (_) => {
|
|
137
|
-
const payloadCopy = Object.assign({}, payload)
|
|
138
|
-
payloadCopy.sequence = ++payload.sequence
|
|
139
|
-
payloadCopy.chunk = null
|
|
140
|
-
payloadCopy.isStream = false
|
|
141
|
-
|
|
142
|
-
// todo: Attach error on payload
|
|
143
|
-
|
|
144
|
-
const message = transport.createMessage(MessageTypes.MESSAGE_REQUEST, context.nodeId, payloadCopy)
|
|
145
|
-
return transport.send(message)
|
|
146
|
-
})
|
|
147
|
-
}
|
|
148
|
-
})
|
|
149
|
-
.catch((error) => {
|
|
150
|
-
reject(error)
|
|
151
|
-
})
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
transport.log = runtime.createLogger('TRANSPORT')
|
|
47
|
+
transport.log = createLogger('TRANSPORT')
|
|
48
|
+
transport.reconnectInProgress = false
|
|
155
49
|
transport.isConnected = false
|
|
50
|
+
transport.isDisconnecting = false
|
|
156
51
|
transport.isReady = false
|
|
157
52
|
transport.pending = pending
|
|
158
53
|
transport.resolveConnect = null
|
|
159
54
|
transport.adapterName = adapter.name
|
|
160
|
-
|
|
161
55
|
transport.statistics = {
|
|
162
56
|
received: {
|
|
163
57
|
packages: 0
|
|
@@ -167,15 +61,24 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
167
61
|
}
|
|
168
62
|
}
|
|
169
63
|
|
|
64
|
+
const getErrorPayload = errorPayloadFactory(runtime)
|
|
65
|
+
|
|
170
66
|
transport.connect = () => {
|
|
171
67
|
return new Promise(resolve => {
|
|
172
68
|
transport.resolveConnect = resolve
|
|
173
69
|
transport.log.info('Connecting to transport adapter...')
|
|
174
70
|
|
|
175
71
|
const doConnect = (isTryReconnect) => {
|
|
176
|
-
const errorHandler = error => {
|
|
72
|
+
const errorHandler = (error) => {
|
|
73
|
+
// Skip reconnect, if the adapter is disconnecting or an reconnect is in progress.
|
|
74
|
+
if (transport.isDisconnecting || transport.reconnectInProgress) {
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
|
|
177
78
|
transport.log.warn('Connection failed')
|
|
178
|
-
transport.log.debug(
|
|
79
|
+
transport.log.debug(error)
|
|
80
|
+
|
|
81
|
+
transport.reconnectInProgress = true
|
|
179
82
|
|
|
180
83
|
if (!error.skipRetry) {
|
|
181
84
|
setTimeout(() => {
|
|
@@ -194,22 +97,28 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
194
97
|
}
|
|
195
98
|
|
|
196
99
|
transport.disconnect = () => {
|
|
197
|
-
|
|
198
|
-
|
|
100
|
+
transport.isDisconnecting = true
|
|
199
101
|
transport.isConnected = false
|
|
200
102
|
transport.isReady = false
|
|
201
103
|
|
|
104
|
+
runtime.eventBus.broadcastLocal('$transporter.disconnected', { isGraceful: true })
|
|
105
|
+
|
|
202
106
|
stopTimers()
|
|
203
107
|
|
|
204
|
-
const message =
|
|
108
|
+
const message = createMessage(MessageTypes.MESSAGE_DISCONNECT)
|
|
205
109
|
return transport.send(message)
|
|
206
|
-
.then(() =>
|
|
110
|
+
.then(() => {
|
|
111
|
+
adapter.close()
|
|
112
|
+
})
|
|
113
|
+
.then(() => {
|
|
114
|
+
transport.isDisconnecting = false
|
|
115
|
+
})
|
|
207
116
|
}
|
|
208
117
|
|
|
209
|
-
transport.setReady = () => {
|
|
118
|
+
transport.setReady = async () => {
|
|
210
119
|
if (transport.isConnected) {
|
|
211
120
|
transport.isReady = true
|
|
212
|
-
transport.sendNodeInfo()
|
|
121
|
+
await transport.sendNodeInfo()
|
|
213
122
|
}
|
|
214
123
|
}
|
|
215
124
|
|
|
@@ -218,16 +127,18 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
218
127
|
* @param {*} sender sender node ID.
|
|
219
128
|
* @returns {Promise} Promise
|
|
220
129
|
*/
|
|
221
|
-
transport.sendNodeInfo = (sender) => {
|
|
130
|
+
transport.sendNodeInfo = async (sender) => {
|
|
222
131
|
if (!transport.isConnected || !transport.isReady) {
|
|
223
132
|
return Promise.resolve()
|
|
224
133
|
}
|
|
225
134
|
|
|
135
|
+
// Collect own node info and send it to remote nodes
|
|
226
136
|
const info = runtime.registry.getLocalNodeInfo()
|
|
227
|
-
const message =
|
|
137
|
+
const message = createMessage(MessageTypes.MESSAGE_INFO, sender, {
|
|
228
138
|
...info,
|
|
229
139
|
instanceId: runtime.state.instanceId
|
|
230
140
|
})
|
|
141
|
+
|
|
231
142
|
return transport.send(message)
|
|
232
143
|
}
|
|
233
144
|
|
|
@@ -236,28 +147,42 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
236
147
|
* @param {TransportMessage} message Message to send
|
|
237
148
|
* @returns {Promise} Promise
|
|
238
149
|
*/
|
|
239
|
-
transport.send = (message) => {
|
|
150
|
+
transport.send = async (message) => {
|
|
240
151
|
transport.statistics.sent.packages = transport.statistics.sent.packages + 1
|
|
241
|
-
log.verbose(`Send ${message.type.toUpperCase()} packet to ${message.targetNodeId || 'all nodes'}`)
|
|
152
|
+
transport.log.verbose(`Send ${message.type.toUpperCase()} packet to ${message.targetNodeId || 'all nodes'}`)
|
|
242
153
|
return adapter.preSend(message)
|
|
243
154
|
}
|
|
244
155
|
|
|
245
156
|
transport.sendPing = (nodeId) => {
|
|
246
|
-
const pingMessage =
|
|
157
|
+
const pingMessage = createMessage(MessageTypes.MESSAGE_PING, nodeId, { dispatchTime: Date.now() })
|
|
247
158
|
return transport.send(pingMessage)
|
|
248
159
|
}
|
|
249
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Send discovery message to all nodes.
|
|
163
|
+
* @returns {void}
|
|
164
|
+
*/
|
|
250
165
|
transport.discoverNodes = () => {
|
|
251
|
-
const discoveryMessage =
|
|
166
|
+
const discoveryMessage = createMessage(MessageTypes.MESSAGE_DISCOVERY)
|
|
252
167
|
transport.send(discoveryMessage)
|
|
253
168
|
}
|
|
254
169
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
170
|
+
/**
|
|
171
|
+
* Send discovery message to all nodes.
|
|
172
|
+
* @param{string} target - Target node ID
|
|
173
|
+
* @returns {Promise<void>} - Promise
|
|
174
|
+
*/
|
|
175
|
+
transport.discoverNode = async (target) => {
|
|
176
|
+
const discoveryMessage = createMessage(MessageTypes.MESSAGE_DISCOVERY, target)
|
|
177
|
+
return transport.send(discoveryMessage)
|
|
258
178
|
}
|
|
259
179
|
|
|
260
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Send an event
|
|
182
|
+
* @param {Context} context - Context
|
|
183
|
+
* @returns {Promise<void>} - Promise
|
|
184
|
+
*/
|
|
185
|
+
transport.sendEvent = async (context) => {
|
|
261
186
|
const isBroadcast = context.eventType === 'broadcast'
|
|
262
187
|
|
|
263
188
|
const payload = {
|
|
@@ -272,12 +197,12 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
272
197
|
isBroadcast
|
|
273
198
|
}
|
|
274
199
|
|
|
275
|
-
const message =
|
|
200
|
+
const message = createMessage(MessageTypes.MESSAGE_EVENT, context.endpoint ? context.nodeId : null, payload)
|
|
276
201
|
return transport.send(message)
|
|
277
202
|
}
|
|
278
203
|
|
|
279
204
|
transport.sendBroadcastEvent = (nodeId, eventName, data, groups) => {
|
|
280
|
-
log.verbose(`Send ${eventName} to ${nodeId}`)
|
|
205
|
+
transport.log.verbose(`Send ${eventName} to ${nodeId}`)
|
|
281
206
|
|
|
282
207
|
const payload = {
|
|
283
208
|
data,
|
|
@@ -286,18 +211,20 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
286
211
|
isBroadcast: true
|
|
287
212
|
}
|
|
288
213
|
|
|
289
|
-
const message =
|
|
290
|
-
transport.send(message)
|
|
214
|
+
const message = createMessage(MessageTypes.MESSAGE_EVENT, nodeId, payload)
|
|
215
|
+
return transport.send(message)
|
|
291
216
|
}
|
|
292
217
|
|
|
293
218
|
transport.removePendingRequestsById = (requestId) => {
|
|
294
219
|
pending.requests.delete(requestId)
|
|
295
220
|
pending.requestStreams.delete(requestId)
|
|
296
221
|
pending.responseStreams.delete(requestId)
|
|
222
|
+
pending.outboundResponseStreams.delete(requestId)
|
|
223
|
+
pending.outboundRequestStreams.delete(requestId)
|
|
297
224
|
}
|
|
298
225
|
|
|
299
226
|
transport.removePendingRequestsByNodeId = (nodeId) => {
|
|
300
|
-
log.debug(`Remove pending requests for node ${nodeId}.`)
|
|
227
|
+
transport.log.debug(`Remove pending requests for node ${nodeId}.`)
|
|
301
228
|
pending.requests.forEach((request, requestId) => {
|
|
302
229
|
if (request.nodeId === nodeId) {
|
|
303
230
|
pending.requests.delete(requestId)
|
|
@@ -309,15 +236,7 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
309
236
|
})
|
|
310
237
|
}
|
|
311
238
|
|
|
312
|
-
transport.
|
|
313
|
-
return {
|
|
314
|
-
type: type || MessageTypes.MESSAGE_UNKNOWN,
|
|
315
|
-
targetNodeId,
|
|
316
|
-
payload: payload || {}
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
transport.request = (context) => {
|
|
239
|
+
transport.sendRequest = (context) => {
|
|
321
240
|
// If the queue size is set, check the queue size and reject the job when the limit is reached.
|
|
322
241
|
if (runtime.options.transport.maxQueueSize && runtime.options.transport.maxQueueSize < pending.requests.size) {
|
|
323
242
|
return Promise.reject(new WeaveQueueSizeExceededError({
|
|
@@ -328,12 +247,146 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
328
247
|
}))
|
|
329
248
|
}
|
|
330
249
|
|
|
331
|
-
return new Promise((resolve, reject) =>
|
|
250
|
+
return new Promise((resolve, reject) => {
|
|
251
|
+
const isStream = utils.isStream(context.options.stream)
|
|
252
|
+
|
|
253
|
+
const request = {
|
|
254
|
+
targetNodeId: context.nodeId,
|
|
255
|
+
action: context.action.name,
|
|
256
|
+
context,
|
|
257
|
+
resolve,
|
|
258
|
+
reject,
|
|
259
|
+
isStream
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
transport.log.debug(`Send request for ${request.action} to node ${request.targetNodeId}.`)
|
|
263
|
+
|
|
264
|
+
pending.requests.set(context.id, request)
|
|
265
|
+
|
|
266
|
+
const payload = {
|
|
267
|
+
id: context.id,
|
|
268
|
+
action: context.action.name,
|
|
269
|
+
data: context.data,
|
|
270
|
+
timeout: context.options.timeout,
|
|
271
|
+
meta: context.meta,
|
|
272
|
+
level: context.level,
|
|
273
|
+
metrics: context.metrics,
|
|
274
|
+
requestId: context.requestId,
|
|
275
|
+
parentId: context.parentId,
|
|
276
|
+
isStream
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Handle object mode streams
|
|
280
|
+
if (isStream) {
|
|
281
|
+
const stream = context.options.stream
|
|
282
|
+
|
|
283
|
+
if (!pending.outboundRequestStreams.has(payload.id)) {
|
|
284
|
+
pending.outboundRequestStreams.set(payload.id, stream)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (utils.isStreamObjectMode(stream)) {
|
|
288
|
+
payload.meta = payload.meta || {}
|
|
289
|
+
payload.meta.$isObjectModeStream = true
|
|
290
|
+
}
|
|
291
|
+
payload.sequence = 0
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const message = createMessage(MessageTypes.MESSAGE_REQUEST, context.nodeId, payload)
|
|
295
|
+
|
|
296
|
+
return transport.send(message)
|
|
297
|
+
.then(() => {
|
|
298
|
+
// send stream
|
|
299
|
+
if (isStream) {
|
|
300
|
+
const stream = context.options.stream
|
|
301
|
+
payload.meta = {}
|
|
302
|
+
|
|
303
|
+
if (utils.isStreamObjectMode(context.options.stream)) {
|
|
304
|
+
payload.meta.$isObjectModeStream = true
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
stream.on('data', data => {
|
|
308
|
+
stream.pause()
|
|
309
|
+
const chunks = []
|
|
310
|
+
|
|
311
|
+
// The chunk is larger than maxBufferSize
|
|
312
|
+
if (data instanceof Buffer && runtime.options.transport.maxChunkSize > 0 && data.length > runtime.options.transport.maxChunkSize) {
|
|
313
|
+
const length = data.length
|
|
314
|
+
let i = 0
|
|
315
|
+
while (i < length) {
|
|
316
|
+
chunks.push(data.slice(i, i += runtime.options.transport.maxChunkSize))
|
|
317
|
+
}
|
|
318
|
+
} else {
|
|
319
|
+
chunks.push(data)
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Send chunks from chunk buffer
|
|
323
|
+
for (const chunk of chunks) {
|
|
324
|
+
const payloadCopy = Object.assign({}, payload)
|
|
325
|
+
payloadCopy.sequence = ++payload.sequence
|
|
326
|
+
payloadCopy.chunk = chunk
|
|
327
|
+
payloadCopy.isStream = true
|
|
328
|
+
payload.data = null
|
|
329
|
+
|
|
330
|
+
const message = createMessage(MessageTypes.MESSAGE_REQUEST, context.nodeId, payloadCopy)
|
|
331
|
+
transport.send(message)
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// resume stream
|
|
335
|
+
stream.resume()
|
|
336
|
+
return
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
stream.on('end', () => {
|
|
340
|
+
const payloadCopy = Object.assign({}, payload)
|
|
341
|
+
|
|
342
|
+
payloadCopy.sequence = ++payload.sequence
|
|
343
|
+
payloadCopy.chunk = null
|
|
344
|
+
payloadCopy.isStream = false
|
|
345
|
+
|
|
346
|
+
pending.outboundRequestStreams.delete(payload.id)
|
|
347
|
+
|
|
348
|
+
const message = createMessage(MessageTypes.MESSAGE_REQUEST, context.nodeId, payloadCopy)
|
|
349
|
+
return transport.send(message)
|
|
350
|
+
})
|
|
351
|
+
|
|
352
|
+
stream.on('error', (error) => {
|
|
353
|
+
const payloadCopy = Object.assign({}, payload)
|
|
354
|
+
payloadCopy.sequence = ++payload.sequence
|
|
355
|
+
payloadCopy.chunk = null
|
|
356
|
+
payloadCopy.isStream = false
|
|
357
|
+
|
|
358
|
+
if (error) {
|
|
359
|
+
payloadCopy.success = false
|
|
360
|
+
payloadCopy.error = getErrorPayload(error)
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
pending.outboundRequestStreams.delete(payload.id)
|
|
364
|
+
|
|
365
|
+
const message = createMessage(MessageTypes.MESSAGE_REQUEST, context.nodeId, payloadCopy)
|
|
366
|
+
return transport.send(message)
|
|
367
|
+
})
|
|
368
|
+
}
|
|
369
|
+
})
|
|
370
|
+
.catch((error) => {
|
|
371
|
+
reject(error)
|
|
372
|
+
})
|
|
373
|
+
})
|
|
332
374
|
}
|
|
333
375
|
|
|
334
|
-
|
|
376
|
+
/**
|
|
377
|
+
* Send response for an open request.
|
|
378
|
+
* @param {string} target - Target node ID
|
|
379
|
+
* @param {string} contextId - Context ID
|
|
380
|
+
* @param {any} data - Data
|
|
381
|
+
* @param {Object} meta - Meta data
|
|
382
|
+
* @param {WeaveError=} error - Error
|
|
383
|
+
* @returns {Promise<void>} - Promise
|
|
384
|
+
*/
|
|
385
|
+
transport.sendResponse = (target, contextId, data, meta, error) => {
|
|
335
386
|
// Check if data is a stream
|
|
336
387
|
const isStream = utils.isStream(data)
|
|
388
|
+
|
|
389
|
+
// Build response payload
|
|
337
390
|
const payload = {
|
|
338
391
|
id: contextId,
|
|
339
392
|
meta,
|
|
@@ -341,20 +394,18 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
341
394
|
success: error == null
|
|
342
395
|
}
|
|
343
396
|
|
|
397
|
+
// If an error is occurs, we attach the an error object to the payload.
|
|
344
398
|
if (error) {
|
|
345
|
-
payload.error =
|
|
346
|
-
name: error.name,
|
|
347
|
-
message: error.message,
|
|
348
|
-
nodeId: error.nodeId || nodeId,
|
|
349
|
-
code: error.code,
|
|
350
|
-
type: error.type,
|
|
351
|
-
stack: error.stack,
|
|
352
|
-
data: error.data
|
|
353
|
-
}
|
|
399
|
+
payload.error = getErrorPayload(error)
|
|
354
400
|
}
|
|
355
401
|
|
|
356
402
|
if (isStream) {
|
|
357
403
|
const stream = data
|
|
404
|
+
|
|
405
|
+
if (!pending.outboundResponseStreams.has(payload.id)) {
|
|
406
|
+
pending.outboundResponseStreams.set(payload.id, stream)
|
|
407
|
+
}
|
|
408
|
+
|
|
358
409
|
payload.data = null
|
|
359
410
|
payload.sequence = 0
|
|
360
411
|
payload.isStream = true
|
|
@@ -388,9 +439,9 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
388
439
|
payloadCopy.sequence = ++payload.sequence
|
|
389
440
|
|
|
390
441
|
payloadCopy.chunk = chunk
|
|
391
|
-
transport.log.debug(
|
|
442
|
+
transport.log.debug(`Send Stream chunk to ${target}`)
|
|
392
443
|
|
|
393
|
-
const message =
|
|
444
|
+
const message = createMessage(MessageTypes.MESSAGE_RESPONSE, target, payloadCopy)
|
|
394
445
|
transport.send(message)
|
|
395
446
|
}
|
|
396
447
|
|
|
@@ -406,10 +457,11 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
406
457
|
payloadCopy.chunk = null
|
|
407
458
|
payloadCopy.isStream = false
|
|
408
459
|
|
|
409
|
-
transport.log.debug(
|
|
460
|
+
transport.log.debug(`Send end stream chunk to ${target}`)
|
|
410
461
|
|
|
411
|
-
const message =
|
|
462
|
+
const message = createMessage(MessageTypes.MESSAGE_RESPONSE, target, payloadCopy)
|
|
412
463
|
transport.send(message)
|
|
464
|
+
pending.outboundResponseStreams.delete(payload.id)
|
|
413
465
|
})
|
|
414
466
|
|
|
415
467
|
stream.on('error', (error) => {
|
|
@@ -421,18 +473,23 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
421
473
|
|
|
422
474
|
if (error) {
|
|
423
475
|
payloadCopy.success = false
|
|
476
|
+
payloadCopy.error = getErrorPayload(error)
|
|
424
477
|
}
|
|
425
|
-
|
|
478
|
+
|
|
479
|
+
transport.log.debug(`Send closing chunk to ${target}`)
|
|
480
|
+
|
|
481
|
+
const message = createMessage(MessageTypes.MESSAGE_RESPONSE, target, payloadCopy)
|
|
426
482
|
transport.send(message)
|
|
483
|
+
pending.outboundResponseStreams.delete(payload.id)
|
|
427
484
|
})
|
|
428
485
|
|
|
429
486
|
payload.data = null
|
|
430
|
-
const message =
|
|
487
|
+
const message = createMessage(MessageTypes.MESSAGE_RESPONSE, target, payload)
|
|
431
488
|
return transport.send(message)
|
|
432
489
|
.then(() => stream.resume())
|
|
433
490
|
}
|
|
434
491
|
|
|
435
|
-
const message =
|
|
492
|
+
const message = createMessage(MessageTypes.MESSAGE_RESPONSE, target, payload)
|
|
436
493
|
return transport.send(message)
|
|
437
494
|
}
|
|
438
495
|
|
|
@@ -510,7 +567,11 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
510
567
|
adapter.subscribe(MessageTypes.MESSAGE_PONG, nodeId),
|
|
511
568
|
adapter.subscribe(MessageTypes.MESSAGE_DISCONNECT),
|
|
512
569
|
adapter.subscribe(MessageTypes.MESSAGE_HEARTBEAT),
|
|
513
|
-
adapter.subscribe(MessageTypes.MESSAGE_EVENT, nodeId)
|
|
570
|
+
adapter.subscribe(MessageTypes.MESSAGE_EVENT, nodeId),
|
|
571
|
+
adapter.subscribe(MessageTypes.MESSAGE_RESPONSE_STREAM_BACKPRESSURE, nodeId),
|
|
572
|
+
adapter.subscribe(MessageTypes.MESSAGE_RESPONSE_STREAM_RESUME, nodeId),
|
|
573
|
+
adapter.subscribe(MessageTypes.MESSAGE_REQUEST_STREAM_BACKPRESSURE, nodeId),
|
|
574
|
+
adapter.subscribe(MessageTypes.MESSAGE_REQUEST_STREAM_RESUME, nodeId)
|
|
514
575
|
])
|
|
515
576
|
}
|
|
516
577
|
|
|
@@ -549,7 +610,7 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
549
610
|
const node = runtime.registry.nodeCollection.localNode
|
|
550
611
|
node.updateLocalInfo()
|
|
551
612
|
|
|
552
|
-
log.verbose(`Send heartbeat from ${node.id}`)
|
|
613
|
+
transport.log.verbose(`Send heartbeat from ${node.id}`)
|
|
553
614
|
|
|
554
615
|
const payload = {
|
|
555
616
|
cpu: node.cpu,
|
|
@@ -557,7 +618,7 @@ exports.createTransport = (runtime, adapter) => {
|
|
|
557
618
|
sequence: node.sequence
|
|
558
619
|
}
|
|
559
620
|
|
|
560
|
-
const message =
|
|
621
|
+
const message = createMessage(MessageTypes.MESSAGE_HEARTBEAT, null, payload)
|
|
561
622
|
transport.send(message)
|
|
562
623
|
}
|
|
563
624
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Payload factory
|
|
3
|
+
* @param {import("../types").Runtime} runtime Runtime
|
|
4
|
+
* @returns {function(Error)} Generate error payload object
|
|
5
|
+
*/
|
|
6
|
+
const errorPayloadFactory = (runtime) => (error) => {
|
|
7
|
+
return {
|
|
8
|
+
name: error.name,
|
|
9
|
+
message: error.message,
|
|
10
|
+
nodeId: error.nodeId || runtime.nodeId,
|
|
11
|
+
code: error.code,
|
|
12
|
+
type: error.type,
|
|
13
|
+
stack: error.stack,
|
|
14
|
+
data: error.data
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
module.exports = { errorPayloadFactory }
|