@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,106 @@
|
|
|
1
|
+
const { isString, isFunction } = require('@weave-js/utils')
|
|
2
|
+
|
|
3
|
+
module.exports = (runtime) => {
|
|
4
|
+
return {
|
|
5
|
+
localAction: (handler, action) => {
|
|
6
|
+
const cacheOptions = runtime.options.cache
|
|
7
|
+
const cacheActionOptions = {
|
|
8
|
+
enabled: !!action.cache
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (isString(action.cache)) {
|
|
12
|
+
cacheActionOptions.keys = action.cache.split(' ')
|
|
13
|
+
} else if (action.cache && Array.isArray(action.cache.keys)) {
|
|
14
|
+
cacheActionOptions.keys = action.cache.keys
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (cacheActionOptions.enabled) {
|
|
18
|
+
const cache = runtime.cache
|
|
19
|
+
const isEnabledFunction = isFunction(action.cache.condition)
|
|
20
|
+
|
|
21
|
+
return function cacheMiddleware (context, serviceInjections) {
|
|
22
|
+
// handle enabled function
|
|
23
|
+
if (isEnabledFunction) {
|
|
24
|
+
if (!action.cache.enabled.call(null, context)) {
|
|
25
|
+
// Enabled function returns "false". Cache is disabled.
|
|
26
|
+
return handler(context, serviceInjections)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Generate cache hash
|
|
31
|
+
const cacheHashKey = cache.getCachingKey(
|
|
32
|
+
action.name,
|
|
33
|
+
context.data,
|
|
34
|
+
context.meta,
|
|
35
|
+
cacheActionOptions.keys
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
context.isCachedResult = false
|
|
39
|
+
|
|
40
|
+
// Disable caching by meta property.
|
|
41
|
+
if (context.meta.$noCache === true) {
|
|
42
|
+
return handler(context, serviceInjections)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// The cache adapter is not connected yet. In this case, we call the handler regular
|
|
46
|
+
if (cache.isConnected === false) {
|
|
47
|
+
cache.log('Cache adapter is not connected yet. Call handler...')
|
|
48
|
+
return handler(context, serviceInjections)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (cacheOptions.lock.enabled) {
|
|
52
|
+
let cachePromise
|
|
53
|
+
if (cacheOptions.lock.staleTime && cache.getWithTTl) {
|
|
54
|
+
|
|
55
|
+
} else {
|
|
56
|
+
cachePromise = runtime.cache.get(cacheHashKey)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return cachePromise.then((cachedResult) => {
|
|
60
|
+
if (cachedResult !== null) {
|
|
61
|
+
// Found a cached value. Skip calling handler and return our value
|
|
62
|
+
context.isCachedResult = true
|
|
63
|
+
return cachedResult
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return cache.lock(cacheHashKey).then((release) => {
|
|
67
|
+
return cache.get(cacheHashKey).then(cachedResult => {
|
|
68
|
+
if (cachedResult !== null) {
|
|
69
|
+
// Found a cached value. Skip calling handler and return our value
|
|
70
|
+
context.isCachedResult = true
|
|
71
|
+
return release().then(() => {
|
|
72
|
+
return cachedResult
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return handler(context).then((result) => {
|
|
77
|
+
// Cache the value
|
|
78
|
+
cache.set(cacheHashKey, result, action.cache.ttl).then(() => {
|
|
79
|
+
// release the lock
|
|
80
|
+
release()
|
|
81
|
+
})
|
|
82
|
+
return result
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Not using cache lock
|
|
90
|
+
return runtime.cache.get(cacheHashKey).then((cachedResult) => {
|
|
91
|
+
if (cachedResult !== null) {
|
|
92
|
+
context.isCachedResult = true
|
|
93
|
+
return cachedResult
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return handler(context, serviceInjections).then((result) => {
|
|
97
|
+
runtime.cache.set(cacheHashKey, result, action.cache.ttl)
|
|
98
|
+
return result
|
|
99
|
+
})
|
|
100
|
+
})
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return handler
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Author: Kevin Ries (kevin@fachw3rk.de)
|
|
3
3
|
* -----
|
|
4
|
-
* Copyright
|
|
4
|
+
* Copyright 2021 Fachwerk
|
|
5
5
|
*/
|
|
6
|
+
const {
|
|
7
|
+
CIRCUIT_CLOSED,
|
|
8
|
+
CIRCUIT_HALF_OPENED,
|
|
9
|
+
CIRCUIT_HALF_OPEN_WAITING,
|
|
10
|
+
CIRCUIT_OPENED
|
|
11
|
+
} = require('../../constants').circuitBreakerStates
|
|
6
12
|
|
|
7
13
|
module.exports = (runtime) => {
|
|
8
14
|
const storage = new Map()
|
|
@@ -15,7 +21,7 @@ module.exports = (runtime) => {
|
|
|
15
21
|
}
|
|
16
22
|
|
|
17
23
|
function clearEndpointStore () {
|
|
18
|
-
storage.forEach(item => {
|
|
24
|
+
storage.forEach((item) => {
|
|
19
25
|
if (item.callCounter === 0) {
|
|
20
26
|
storage.delete(item.name)
|
|
21
27
|
return
|
|
@@ -34,7 +40,7 @@ module.exports = (runtime) => {
|
|
|
34
40
|
options,
|
|
35
41
|
callCounter: 0,
|
|
36
42
|
failureCouter: 0,
|
|
37
|
-
state:
|
|
43
|
+
state: CIRCUIT_CLOSED,
|
|
38
44
|
circuitBreakerTimer: null
|
|
39
45
|
}
|
|
40
46
|
storage.set(endpoint.name, item)
|
|
@@ -43,17 +49,17 @@ module.exports = (runtime) => {
|
|
|
43
49
|
return item
|
|
44
50
|
}
|
|
45
51
|
|
|
46
|
-
function
|
|
52
|
+
function onSuccess (item, options) {
|
|
47
53
|
item.callCounter++
|
|
48
54
|
|
|
49
|
-
if (item.state ===
|
|
50
|
-
closeCircuitBreaker(item
|
|
55
|
+
if (item.state === CIRCUIT_HALF_OPENED) {
|
|
56
|
+
closeCircuitBreaker(item)
|
|
51
57
|
} else {
|
|
52
58
|
checkThreshold(item, options)
|
|
53
59
|
}
|
|
54
60
|
}
|
|
55
61
|
|
|
56
|
-
function
|
|
62
|
+
function onFailure (item, options) {
|
|
57
63
|
item.callCounter++
|
|
58
64
|
item.failureCouter++
|
|
59
65
|
|
|
@@ -67,24 +73,36 @@ module.exports = (runtime) => {
|
|
|
67
73
|
}
|
|
68
74
|
|
|
69
75
|
function openCircuitBreaker (item) {
|
|
70
|
-
item.state =
|
|
76
|
+
item.state = CIRCUIT_OPENED
|
|
71
77
|
item.endpoint.state = false
|
|
72
78
|
item.circuitBreakerTimer = setTimeout(() => halfOpenCircuitBreaker(item), item.options.halfOpenTimeout)
|
|
73
|
-
|
|
79
|
+
item.circuitBreakerTimer.unref()
|
|
74
80
|
log.debug(`Circuit breaker has been opened for endpoint '${item.endpoint.name}'`)
|
|
75
81
|
}
|
|
76
82
|
|
|
77
83
|
function halfOpenCircuitBreaker (item) {
|
|
78
|
-
item.state =
|
|
84
|
+
item.state = CIRCUIT_HALF_OPENED
|
|
79
85
|
item.endpoint.state = true
|
|
80
86
|
|
|
81
87
|
log.debug(`Circuit breaker has been half opened for endpoint '${item.endpoint.name}'`)
|
|
88
|
+
|
|
89
|
+
if (item.circuitBreakerTimer) {
|
|
90
|
+
clearTimeout(item.circuitBreakerTimer)
|
|
91
|
+
item.circuitBreakerTimer = null
|
|
92
|
+
}
|
|
82
93
|
}
|
|
83
94
|
|
|
84
|
-
function
|
|
95
|
+
function handleHalfOpen (item) {
|
|
96
|
+
item.state = CIRCUIT_HALF_OPEN_WAITING
|
|
97
|
+
item.endpoint.state = false
|
|
98
|
+
item.circuitBreakerTimer = setTimeout(() => halfOpenCircuitBreaker(item), item.options.halfOpenTimeout)
|
|
99
|
+
item.circuitBreakerTimer.unref()
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function closeCircuitBreaker (item) {
|
|
85
103
|
item.failureCouter = 0
|
|
86
104
|
item.callCounter = 0
|
|
87
|
-
item.state =
|
|
105
|
+
item.state = CIRCUIT_CLOSED
|
|
88
106
|
item.endpoint.state = true
|
|
89
107
|
|
|
90
108
|
if (item.circuitBreakerTimer) {
|
|
@@ -99,19 +117,26 @@ module.exports = (runtime) => {
|
|
|
99
117
|
const options = Object.assign({}, runtime.options.circuitBreaker, action.circuitBreaker || {})
|
|
100
118
|
|
|
101
119
|
if (options.enabled) {
|
|
102
|
-
return function curcuitBreakerMiddleware (context) {
|
|
120
|
+
return function curcuitBreakerMiddleware (context, serviceInjections) {
|
|
103
121
|
const endpoint = context.endpoint
|
|
104
122
|
const item = getEndpointState(endpoint, options)
|
|
105
123
|
|
|
106
|
-
|
|
124
|
+
// handle half open states
|
|
125
|
+
if (item.state === CIRCUIT_HALF_OPENED) {
|
|
126
|
+
handleHalfOpen(item, context)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return handler(context, serviceInjections)
|
|
107
130
|
.then(result => {
|
|
108
131
|
const item = getEndpointState(endpoint, options)
|
|
109
|
-
|
|
132
|
+
onSuccess(item, options)
|
|
110
133
|
|
|
111
134
|
return result
|
|
112
135
|
})
|
|
113
136
|
.catch(error => {
|
|
114
|
-
|
|
137
|
+
if (item && (!error.nodeId || error.nodeId === context.nodeId)) {
|
|
138
|
+
onFailure(item, options)
|
|
139
|
+
}
|
|
115
140
|
|
|
116
141
|
return Promise.reject(error)
|
|
117
142
|
})
|
|
@@ -27,16 +27,16 @@ module.exports = (runtime) => {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
function wrapContextTrackerMiddleware (actionHandler) {
|
|
30
|
-
return function ContextTrackerMiddleware (context) {
|
|
30
|
+
return function ContextTrackerMiddleware (context, serviceInjections) {
|
|
31
31
|
const isTracked = context.options.track === true ? context.options.track : runtime.options.contextTracking.enabled
|
|
32
32
|
|
|
33
33
|
if (!isTracked) {
|
|
34
|
-
return actionHandler(context)
|
|
34
|
+
return actionHandler(context, serviceInjections)
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
addContext(context)
|
|
38
38
|
|
|
39
|
-
return actionHandler(context)
|
|
39
|
+
return actionHandler(context, serviceInjections)
|
|
40
40
|
.then(result => {
|
|
41
41
|
removeContext(context)
|
|
42
42
|
return result
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Author: Kevin Ries (kevin@fachw3rk.de)
|
|
3
3
|
* -----
|
|
4
|
-
* Copyright
|
|
4
|
+
* Copyright 2021 Fachwerk
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const { WeaveError } = require('../../errors')
|
|
8
8
|
|
|
9
9
|
module.exports = (runtime) => {
|
|
10
10
|
const wrapErrorHandlerMiddleware = function (handler) {
|
|
11
|
-
return function errorHandlerMiddleware (context) {
|
|
12
|
-
return handler(context)
|
|
11
|
+
return function errorHandlerMiddleware (context, serviceInjections) {
|
|
12
|
+
return handler(context, serviceInjections)
|
|
13
13
|
.catch(error => {
|
|
14
14
|
if (!(error instanceof Error)) {
|
|
15
15
|
error = new WeaveError(error, 500)
|
package/lib/middlewares/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Author: Kevin Ries (kevin@fachw3rk.de)
|
|
3
3
|
* -----
|
|
4
|
-
* Copyright
|
|
4
|
+
* Copyright 2021 Fachwerk
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
ActionHooks: require('./action-hooks'),
|
|
9
9
|
Bulkhead: require('./bulkhead'),
|
|
10
|
+
Cache: require('./cache'),
|
|
10
11
|
CircuitBreaker: require('./circuit-breaker'),
|
|
11
12
|
ErrorHandler: require('./error-handler'),
|
|
12
13
|
Metrics: require('./metrics'),
|
|
@@ -4,14 +4,14 @@ module.exports.getMiddlewareWrapper = (runtime) => function (type, action, handl
|
|
|
4
4
|
const serviceName = action.service ? action.service.fullyQualifiedName : null
|
|
5
5
|
const actionName = action.name
|
|
6
6
|
|
|
7
|
-
return function metricMiddleware (context) {
|
|
7
|
+
return function metricMiddleware (context, serviceInjections) {
|
|
8
8
|
const callerNodeId = context.callerNodeId
|
|
9
9
|
|
|
10
10
|
runtime.metrics.increment(Constants.REQUESTS_TOTAL, { type, serviceName, actionName, callerNodeId })
|
|
11
11
|
runtime.metrics.increment(Constants.REQUESTS_IN_FLIGHT, { type, serviceName, actionName, callerNodeId })
|
|
12
12
|
const requestEnd = runtime.metrics.timer(Constants.REQUESTS_TIME, { type, serviceName, actionName, callerNodeId })
|
|
13
13
|
|
|
14
|
-
return handler(context)
|
|
14
|
+
return handler(context, serviceInjections)
|
|
15
15
|
.then(result => {
|
|
16
16
|
requestEnd()
|
|
17
17
|
runtime.metrics.decrement(Constants.REQUESTS_IN_FLIGHT, { type, serviceName, actionName, callerNodeId })
|
|
@@ -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
|
const { Constants } = require('../../metrics')
|
|
7
7
|
const { getMiddlewareWrapper } = require('./getMiddlewareWrapper')
|
|
@@ -33,7 +33,7 @@ module.exports = (runtime) => {
|
|
|
33
33
|
return wrapMetricMiddleware('local', action, next)
|
|
34
34
|
},
|
|
35
35
|
remoteAction (next, action) {
|
|
36
|
-
return wrapMetricMiddleware
|
|
36
|
+
return wrapMetricMiddleware('remote', action, next)
|
|
37
37
|
},
|
|
38
38
|
emit (next) {
|
|
39
39
|
return (event, payload) => {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/*
|
|
3
3
|
* Author: Kevin Ries (kevin@fachw3rk.de)
|
|
4
4
|
* -----
|
|
5
|
-
* Copyright
|
|
5
|
+
* Copyright 2021 Fachwerk
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const { delay } = require('@weave-js/utils')
|
|
@@ -14,7 +14,7 @@ const wrapRetryMiddleware = function (handler, action) {
|
|
|
14
14
|
// middleware is enabled
|
|
15
15
|
if (options.enabled) {
|
|
16
16
|
// Return middlware handler
|
|
17
|
-
return function retryMiddleware (context) {
|
|
17
|
+
return function retryMiddleware (context, serviceInjections) {
|
|
18
18
|
// if the context has no repeat count, set it to zero.
|
|
19
19
|
if (context.retryCount === undefined) {
|
|
20
20
|
context.retryCount = 0
|
|
@@ -22,14 +22,15 @@ const wrapRetryMiddleware = function (handler, action) {
|
|
|
22
22
|
|
|
23
23
|
const attempts = typeof context.options.retries === 'number' ? context.options.retries : options.retries
|
|
24
24
|
|
|
25
|
-
return handler(context)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
25
|
+
return handler(context, serviceInjections)
|
|
26
|
+
.catch(error => {
|
|
27
|
+
if (context.retryCount++ < attempts && error.retryable === true) {
|
|
28
|
+
self.log.warn(`Retry to recall action '${context.action.name}' after ${options.delay}.`)
|
|
29
|
+
return delay(options.delay)
|
|
30
|
+
.then(() => self.call(context.action.name, context.data, { context }))
|
|
31
|
+
}
|
|
32
|
+
return Promise.reject(error)
|
|
33
|
+
})
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
return handler
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Author: Kevin Ries (kevin@fachw3rk.de)
|
|
3
3
|
* -----
|
|
4
|
-
* Copyright
|
|
4
|
+
* Copyright 2021 Fachwerk
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const { promiseTimeout } = require('@weave-js/utils')
|
|
8
8
|
const { WeaveRequestTimeoutError } = require('../../errors')
|
|
9
9
|
|
|
10
|
-
const wrapTimeoutMiddleware = function (handler
|
|
10
|
+
const wrapTimeoutMiddleware = function (handler) {
|
|
11
11
|
const self = this
|
|
12
12
|
const registryOptions = self.options.registry || {}
|
|
13
13
|
|
|
14
|
-
return function timeoutMiddleware (context) {
|
|
14
|
+
return function timeoutMiddleware (context, serviceInjections) {
|
|
15
15
|
if (typeof context.options.timeout === 'undefined' || registryOptions.requestTimeout) {
|
|
16
16
|
context.options.timeout = registryOptions.requestTimeout || 0
|
|
17
17
|
}
|
|
@@ -20,10 +20,10 @@ const wrapTimeoutMiddleware = function (handler, action) {
|
|
|
20
20
|
context.startHighResolutionTime = process.hrtime()
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
let promise = handler(context)
|
|
23
|
+
let promise = handler(context, serviceInjections)
|
|
24
24
|
|
|
25
25
|
if (context.options.timeout > 0) {
|
|
26
|
-
promise = promiseTimeout(context.options.timeout, promise, new WeaveRequestTimeoutError(context.action.name, context.nodeId))
|
|
26
|
+
promise = promiseTimeout(context.options.timeout, promise, new WeaveRequestTimeoutError(context.action.name, context.nodeId, context.options.timeout))
|
|
27
27
|
.catch(error => {
|
|
28
28
|
if (error instanceof WeaveRequestTimeoutError) {
|
|
29
29
|
self.log.warn(`Request '${context.action.name}' timed out.`)
|
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Author: Kevin Ries (kevin@fachw3rk.de)
|
|
3
3
|
* -----
|
|
4
|
-
* Copyright
|
|
4
|
+
* Copyright 2021 Fachwerk
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const {
|
|
7
|
+
const { isPlainObject } = require('@weave-js/utils')
|
|
8
|
+
const { buildActionTags, buildEventTags } = require('./tags')
|
|
8
9
|
|
|
9
10
|
const wrapTracingLocalActionMiddleware = function (handler) {
|
|
10
11
|
const broker = this
|
|
11
|
-
const
|
|
12
|
+
const tracingOptions = broker.options.tracing || {}
|
|
12
13
|
|
|
13
|
-
if (
|
|
14
|
-
return function metricsLocalMiddleware (context) {
|
|
15
|
-
const tags =
|
|
14
|
+
if (tracingOptions.enabled) {
|
|
15
|
+
return function metricsLocalMiddleware (context, serviceInjections) {
|
|
16
|
+
const tags = buildActionTags(context, tracingOptions)
|
|
17
|
+
|
|
18
|
+
if (tracingOptions) {
|
|
19
|
+
tags.data = context.data !== null && isPlainObject(context.data) ? Object.assign({}, context.data) : context.data
|
|
20
|
+
}
|
|
16
21
|
|
|
17
|
-
const spanName = `action
|
|
22
|
+
const spanName = `action "${context.action.name}"`
|
|
18
23
|
|
|
19
24
|
const span = context.startSpan(spanName, {
|
|
20
25
|
id: context.id,
|
|
@@ -28,8 +33,17 @@ const wrapTracingLocalActionMiddleware = function (handler) {
|
|
|
28
33
|
|
|
29
34
|
context.span = span
|
|
30
35
|
|
|
31
|
-
return handler(context)
|
|
36
|
+
return handler(context, serviceInjections)
|
|
32
37
|
.then(result => {
|
|
38
|
+
const tags = {
|
|
39
|
+
isCachedResult: context.isCachedResult
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (tracingOptions) {
|
|
43
|
+
tags.response = result !== null && isPlainObject(result) ? Object.assign({}, result) : result
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
span.addTags(tags)
|
|
33
47
|
span.finish()
|
|
34
48
|
return result
|
|
35
49
|
})
|
|
@@ -47,13 +61,13 @@ const wrapTracingLocalActionMiddleware = function (handler) {
|
|
|
47
61
|
const wrapTracingLocalEventMiddleware = function (handler, event) {
|
|
48
62
|
const broker = this
|
|
49
63
|
const service = event.service
|
|
50
|
-
const
|
|
64
|
+
const tracingOptions = broker.options.tracing || {}
|
|
51
65
|
|
|
52
|
-
if (
|
|
66
|
+
if (tracingOptions.enabled) {
|
|
53
67
|
return function metricsLocalMiddleware (context) {
|
|
54
|
-
const tags =
|
|
68
|
+
const tags = buildEventTags(context)
|
|
55
69
|
|
|
56
|
-
const span = context.startSpan(`event
|
|
70
|
+
const span = context.startSpan(`event "${context.eventName}"`, {
|
|
57
71
|
id: context.id,
|
|
58
72
|
traceId: context.requestId,
|
|
59
73
|
parentId: context.parentId,
|
|
@@ -67,7 +81,6 @@ const wrapTracingLocalEventMiddleware = function (handler, event) {
|
|
|
67
81
|
|
|
68
82
|
return handler(context)
|
|
69
83
|
.then(result => {
|
|
70
|
-
span.addTags(tags)
|
|
71
84
|
span.finish()
|
|
72
85
|
return result
|
|
73
86
|
})
|
|
@@ -82,7 +95,7 @@ const wrapTracingLocalEventMiddleware = function (handler, event) {
|
|
|
82
95
|
return handler
|
|
83
96
|
}
|
|
84
97
|
|
|
85
|
-
module.exports = (
|
|
98
|
+
module.exports = () => {
|
|
86
99
|
return {
|
|
87
100
|
localAction: wrapTracingLocalActionMiddleware,
|
|
88
101
|
localEvent: wrapTracingLocalEventMiddleware
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {import("../../types.js").Context} Context
|
|
3
|
+
* @typedef {import("../../types.js").TracingOptions} TracingOptions
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Build span tags object
|
|
8
|
+
* @param {Context} context - Context
|
|
9
|
+
* @param {TracingOptions} brokerTracingOptions - Tracing options
|
|
10
|
+
* @param {TracingOptions} actionTracingOptions - Tracing options
|
|
11
|
+
* @returns {object} Tags
|
|
12
|
+
*/
|
|
13
|
+
module.exports.buildActionTags = (context, brokerTracingOptions, actionTracingOptions) => {
|
|
14
|
+
const tags = {
|
|
15
|
+
requestLevel: context.level,
|
|
16
|
+
action: context.action ? { name: context.action.name, shortName: context.action.shortName } : null,
|
|
17
|
+
isRemoteCall: !!context.callerNodeId,
|
|
18
|
+
nodeId: context.nodeId,
|
|
19
|
+
requestId: context.requestId
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return tags
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Build span tags object
|
|
27
|
+
* @param {Context} context - Context
|
|
28
|
+
* @param {TracingOptions} brokerTracingOptions - Tracing options
|
|
29
|
+
* @param {TracingOptions} actionTracingOptions - Tracing options
|
|
30
|
+
* @returns {object} Tags
|
|
31
|
+
*/
|
|
32
|
+
module.exports.buildEventTags = (context, brokerTracingOptions, actionTracingOptions) => {
|
|
33
|
+
const tags = {
|
|
34
|
+
requestLevel: context.level,
|
|
35
|
+
event: context.eventName,
|
|
36
|
+
eventType: context.eventType,
|
|
37
|
+
isRemoteCall: !!context.callerNodeId,
|
|
38
|
+
nodeId: context.nodeId,
|
|
39
|
+
requestId: context.requestId
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return tags
|
|
43
|
+
}
|
|
@@ -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
|
const { WeaveParameterValidationError } = require('../../errors')
|
|
@@ -16,7 +16,7 @@ const { capitalize } = require('@weave-js/utils')
|
|
|
16
16
|
* Create validator middleware
|
|
17
17
|
* @param {Runtime} runtime - Runtime reference
|
|
18
18
|
* @returns {Middleware} - Validator middleware
|
|
19
|
-
|
|
19
|
+
*/
|
|
20
20
|
module.exports = (runtime) => {
|
|
21
21
|
const validator = runtime.validator
|
|
22
22
|
|
|
@@ -47,11 +47,11 @@ module.exports = (runtime) => {
|
|
|
47
47
|
return handler
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
return (context) => {
|
|
50
|
+
return (context, serviceInjections) => {
|
|
51
51
|
const requestSchemaResult = validateRequestSchema ? validateRequestSchema(context.data) : true
|
|
52
52
|
|
|
53
53
|
if (requestSchemaResult === true) {
|
|
54
|
-
return handler(context)
|
|
54
|
+
return handler(context, serviceInjections)
|
|
55
55
|
.then((result) => {
|
|
56
56
|
if (validateResponseSchema) {
|
|
57
57
|
const responseSchemaResult = validateResponseSchema(result)
|
|
@@ -77,11 +77,11 @@ module.exports = (runtime) => {
|
|
|
77
77
|
|
|
78
78
|
const validate = validator.compile(event.params, parameterOptions)
|
|
79
79
|
|
|
80
|
-
return (context) => {
|
|
80
|
+
return (context, serviceInjections) => {
|
|
81
81
|
let result = validate(context.data)
|
|
82
82
|
|
|
83
83
|
if (result === true) {
|
|
84
|
-
return handler(context)
|
|
84
|
+
return handler(context, serviceInjections)
|
|
85
85
|
} else {
|
|
86
86
|
result = result.map(data => Object.assign(data, { nodeId: context.nodeId, event: context.eventName }))
|
|
87
87
|
return Promise.reject(new WeaveParameterValidationError('Parameter validation error', result))
|
|
File without changes
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/*
|
|
4
4
|
* Author: Kevin Ries (kevin@fachw3rk.de)
|
|
5
5
|
* -----
|
|
6
|
-
* Copyright
|
|
6
|
+
* Copyright 2021 Fachwerk
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* @typedef {import('../../types.js').ServiceActionCollection} ServiceActionCollection
|
|
12
12
|
*/
|
|
13
13
|
const { omit } = require('@weave-js/utils')
|
|
14
|
-
const { createEndpointList } = require('./
|
|
14
|
+
const { createEndpointList } = require('./endpointCollection')
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Configuration object for weave service broker.
|
|
@@ -3,20 +3,36 @@
|
|
|
3
3
|
/*
|
|
4
4
|
* Author: Kevin Ries (kevin@fachw3rk.de)
|
|
5
5
|
* -----
|
|
6
|
-
* Copyright
|
|
6
|
+
* Copyright 2021 Fachwerk
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* @typedef {import('../../types.js').Runtime} Runtime
|
|
11
|
+
* @typedef {import('../../types.js').EventCollection} EventCollection
|
|
12
|
+
* @typedef {import('../../types.js').Service} Service
|
|
13
|
+
* @typedef {import('../../types.js').Node} Node
|
|
14
|
+
* @typedef {import('../../types.js').EndpointCollection} EndpointCollection
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const { createActionEndpoint } = require('../actionEndpoint')
|
|
10
18
|
const { loadBalancingStrategy } = require('../../constants')
|
|
11
19
|
|
|
20
|
+
/**
|
|
21
|
+
*
|
|
22
|
+
* @param {Runtime} runtime Runtime instance
|
|
23
|
+
* @param {string} name name
|
|
24
|
+
* @param {string=} groupName Group name
|
|
25
|
+
* @returns {EndpointCollection} EndpointCollection
|
|
26
|
+
*/
|
|
12
27
|
exports.createEndpointList = (runtime, name, groupName) => {
|
|
28
|
+
/** @type {EndpointCollection} */
|
|
13
29
|
const endpointList = Object.create(null)
|
|
14
30
|
const options = runtime.options
|
|
31
|
+
/** @type {Array} */
|
|
15
32
|
const list = endpointList.endpoints = []
|
|
16
33
|
|
|
17
34
|
let counter = 0
|
|
18
35
|
|
|
19
|
-
endpointList.state = runtime // ????
|
|
20
36
|
endpointList.name = name
|
|
21
37
|
endpointList.groupName = groupName
|
|
22
38
|
endpointList.isInternal = name.startsWith('$')
|