@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
package/lib/logger/base.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const { isStandardLevel, levelMethods } = require('./levels')
|
|
2
|
-
const { noop, generateLogMethod
|
|
2
|
+
const { noop, generateLogMethod } = require('./tools')
|
|
3
3
|
|
|
4
4
|
exports.initBase = (runtime) => {
|
|
5
5
|
runtime.setLevel = (level) => {
|
|
@@ -16,7 +16,7 @@ exports.initBase = (runtime) => {
|
|
|
16
16
|
const hook = runtime.options.hooks.logMethod
|
|
17
17
|
|
|
18
18
|
for (const key in values) {
|
|
19
|
-
if (levelVal
|
|
19
|
+
if (levelVal < values[key]) {
|
|
20
20
|
runtime.logMethods[key] = noop
|
|
21
21
|
continue
|
|
22
22
|
}
|
|
@@ -47,7 +47,7 @@ exports.initBase = (runtime) => {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
const logString =
|
|
50
|
+
const logString = runtime.formatter(runtime, object, message, number, time)
|
|
51
51
|
|
|
52
52
|
runtime.destination.write(logString)
|
|
53
53
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const { green, magenta, red, yellow, gray, cyan } = require('../utils/colorize')
|
|
2
|
+
const os = require('os')
|
|
3
|
+
|
|
4
|
+
exports.asHumanReadable = ({ levels, options }, originObj, message, number, time) => {
|
|
5
|
+
let logResult = ''
|
|
6
|
+
|
|
7
|
+
const logLevelColors = {
|
|
8
|
+
fatal: magenta,
|
|
9
|
+
error: red,
|
|
10
|
+
warn: yellow,
|
|
11
|
+
info: green,
|
|
12
|
+
debug: cyan,
|
|
13
|
+
verbose: gray
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const currentLabel = levels.labels[number]
|
|
17
|
+
|
|
18
|
+
const color = logLevelColors[currentLabel] || yellow
|
|
19
|
+
// Log level label
|
|
20
|
+
logResult += color(currentLabel.toUpperCase())
|
|
21
|
+
|
|
22
|
+
// date time
|
|
23
|
+
logResult += ' [' + new Date(time).toISOString() + '] '
|
|
24
|
+
|
|
25
|
+
if (options.base.pid && options.base.hostname) {
|
|
26
|
+
logResult += ` (${options.base.pid} on ${options.base.hostname})`
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (message) {
|
|
30
|
+
logResult += ' ' + color(message)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (Object.keys(originObj).length > 0) {
|
|
34
|
+
// logResult += gray(' Json:')
|
|
35
|
+
logResult += os.EOL
|
|
36
|
+
logResult += gray(JSON.stringify(originObj, null, 2))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
logResult += os.EOL
|
|
40
|
+
|
|
41
|
+
return logResult
|
|
42
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const os = require('os')
|
|
2
|
+
|
|
3
|
+
exports.asJson = (runtime, originObj, message, number, time) => {
|
|
4
|
+
const data = {
|
|
5
|
+
level: number,
|
|
6
|
+
time,
|
|
7
|
+
...runtime.fixtures
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
if (message !== undefined) {
|
|
11
|
+
data[runtime.options.messageKey] = message
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const notHasOwnProperty = originObj.hasOwnProperty === undefined
|
|
15
|
+
|
|
16
|
+
let value
|
|
17
|
+
for (const key in originObj) {
|
|
18
|
+
value = originObj[key]
|
|
19
|
+
if ((notHasOwnProperty || originObj.hasOwnProperty(key)) && value !== undefined) {
|
|
20
|
+
data[key] = value
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return JSON.stringify(data) + os.EOL
|
|
25
|
+
}
|
package/lib/logger/index.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
const os = require('os')
|
|
8
8
|
const { initBase } = require('./base')
|
|
9
|
+
const { asJson, asHumanReadable } = require('./format')
|
|
9
10
|
const { mappings } = require('./levels')
|
|
10
11
|
const { coreFixtures } = require('./tools')
|
|
11
12
|
|
|
@@ -17,10 +18,16 @@ const defaultOptions = {
|
|
|
17
18
|
level: 'info',
|
|
18
19
|
messageKey: 'message',
|
|
19
20
|
customLevels: null,
|
|
20
|
-
base: {
|
|
21
|
+
base: {
|
|
22
|
+
pid,
|
|
23
|
+
hostname
|
|
24
|
+
},
|
|
21
25
|
hooks: {
|
|
22
26
|
logMethod: undefined
|
|
23
27
|
},
|
|
28
|
+
formatter: {
|
|
29
|
+
messageFormat: false
|
|
30
|
+
},
|
|
24
31
|
destination: process.stdout
|
|
25
32
|
}
|
|
26
33
|
|
|
@@ -31,7 +38,8 @@ exports.createLogger = (options) => {
|
|
|
31
38
|
const runtime = {
|
|
32
39
|
options,
|
|
33
40
|
logMethods: {},
|
|
34
|
-
destination: options.destination
|
|
41
|
+
destination: options.destination,
|
|
42
|
+
formatter: process.stdout.isTTY ? asHumanReadable : asJson
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
if (options.enabled === false) {
|
|
@@ -54,9 +62,8 @@ exports.createLogger = (options) => {
|
|
|
54
62
|
|
|
55
63
|
const levels = mappings(options.customLevels)
|
|
56
64
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
})
|
|
65
|
+
// merge levels in logger runtime
|
|
66
|
+
Object.assign(runtime, { levels })
|
|
60
67
|
|
|
61
68
|
initBase(runtime)
|
|
62
69
|
|
package/lib/logger/levels.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
const { generateLogMethod } = require('./tools')
|
|
2
2
|
|
|
3
3
|
const levels = {
|
|
4
|
-
verbose:
|
|
5
|
-
debug:
|
|
6
|
-
info:
|
|
7
|
-
warn:
|
|
8
|
-
error:
|
|
9
|
-
fatal:
|
|
4
|
+
verbose: 60,
|
|
5
|
+
debug: 50,
|
|
6
|
+
info: 40,
|
|
7
|
+
warn: 30,
|
|
8
|
+
error: 20,
|
|
9
|
+
fatal: 10
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
// wrap log methods
|
|
12
13
|
const levelMethods = {
|
|
13
14
|
fatal: (runtime, hook) => {
|
|
14
15
|
const logFatal = generateLogMethod(runtime, levels.fatal, hook)
|
|
@@ -50,8 +51,9 @@ exports.mappings = (customLevels = null, useOnlyCustomLevels = false) => {
|
|
|
50
51
|
customNums
|
|
51
52
|
)
|
|
52
53
|
|
|
54
|
+
// Merge log levels with "silent" log level.
|
|
53
55
|
const values = Object.assign(
|
|
54
|
-
Object.create(Object.prototype, { silent: { value:
|
|
56
|
+
Object.create(Object.prototype, { silent: { value: 0 }}),
|
|
55
57
|
useOnlyCustomLevels ? null : levels,
|
|
56
58
|
customLevels
|
|
57
59
|
)
|
|
@@ -76,4 +78,3 @@ exports.isStandardLevel = (level, useOnlyCustomLevels) => {
|
|
|
76
78
|
return false
|
|
77
79
|
}
|
|
78
80
|
}
|
|
79
|
-
|
package/lib/logger/tools.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const os = require('os')
|
|
2
1
|
const { format } = require('./utils/format')
|
|
3
2
|
|
|
4
3
|
exports.noop = () => {}
|
|
@@ -8,6 +7,10 @@ exports.generateLogMethod = (runtime, level, hook) => {
|
|
|
8
7
|
return log
|
|
9
8
|
}
|
|
10
9
|
|
|
10
|
+
return function hookWrappedLog (...args) {
|
|
11
|
+
hook.call(runtime, args, log, level)
|
|
12
|
+
}
|
|
13
|
+
|
|
11
14
|
function log (origin, ...n) {
|
|
12
15
|
if (typeof origin === 'object') {
|
|
13
16
|
let message = origin
|
|
@@ -25,30 +28,6 @@ exports.generateLogMethod = (runtime, level, hook) => {
|
|
|
25
28
|
}
|
|
26
29
|
}
|
|
27
30
|
|
|
28
|
-
exports.asJsonString = (runtime, originObj, message, number, time) => {
|
|
29
|
-
const data = {
|
|
30
|
-
level: number,
|
|
31
|
-
time,
|
|
32
|
-
...runtime.fixtures
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (message !== undefined) {
|
|
36
|
-
data[runtime.options.messageKey] = message
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const notHasOwnProperty = originObj.hasOwnProperty === undefined
|
|
40
|
-
|
|
41
|
-
let value
|
|
42
|
-
for (const key in originObj) {
|
|
43
|
-
value = originObj[key]
|
|
44
|
-
if ((notHasOwnProperty || originObj.hasOwnProperty(key)) && value !== undefined) {
|
|
45
|
-
data[key] = value
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return JSON.stringify(data) + os.EOL
|
|
50
|
-
}
|
|
51
|
-
|
|
52
31
|
exports.coreFixtures = (object) => {
|
|
53
32
|
return object
|
|
54
33
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
const init = (x, y) => {
|
|
2
|
+
const regex = new RegExp(`\\x1b\\[${y}m`, 'g')
|
|
3
|
+
const open = `\x1b[${x}m`; const close = `\x1b[${y}m`
|
|
4
|
+
|
|
5
|
+
return function (txt) {
|
|
6
|
+
return open + (~('' + txt).indexOf(close) ? txt.replace(regex, close + open) : txt) + close
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// modifiers
|
|
11
|
+
exports.bold = init(1, 22)
|
|
12
|
+
exports.dim = init(2, 22)
|
|
13
|
+
exports.hidden = init(8, 28)
|
|
14
|
+
exports.inverse = init(7, 27)
|
|
15
|
+
exports.italic = init(3, 23)
|
|
16
|
+
exports.reset = init(0, 0)
|
|
17
|
+
exports.strikeThrough = init(9, 29)
|
|
18
|
+
exports.underline = init(4, 24)
|
|
19
|
+
|
|
20
|
+
// colors
|
|
21
|
+
exports.black = init(30, 39)
|
|
22
|
+
exports.blue = init(34, 39)
|
|
23
|
+
exports.cyan = init(36, 39)
|
|
24
|
+
exports.gray = init(90, 39)
|
|
25
|
+
exports.green = init(32, 39)
|
|
26
|
+
exports.grey = init(90, 39)
|
|
27
|
+
exports.magenta = init(35, 39)
|
|
28
|
+
exports.red = init(31, 39)
|
|
29
|
+
exports.white = init(37, 39)
|
|
30
|
+
exports.yellow = init(33, 39)
|
|
31
|
+
|
|
32
|
+
// todo: bg colors
|
|
@@ -52,29 +52,43 @@ exports.format = (f, args, opts) => {
|
|
|
52
52
|
case 79: // 'O'
|
|
53
53
|
case 111: // 'o'
|
|
54
54
|
case 106: // 'j'
|
|
55
|
-
if (a >= argumentLength) {
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
if (a >= argumentLength) {
|
|
56
|
+
break
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (lastPos < i) {
|
|
60
|
+
str += f.slice(lastPos, i)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (args[a] === undefined) {
|
|
64
|
+
break
|
|
65
|
+
}
|
|
66
|
+
|
|
58
67
|
const type = typeof args[a]
|
|
68
|
+
|
|
59
69
|
if (type === 'string') {
|
|
60
70
|
str += '\'' + args[a] + '\''
|
|
61
71
|
lastPos = i + 2
|
|
62
72
|
i++
|
|
63
73
|
break
|
|
64
74
|
}
|
|
75
|
+
|
|
65
76
|
if (type === 'function') {
|
|
66
77
|
str += args[a].name || '<anonymous>'
|
|
67
78
|
lastPos = i + 2
|
|
68
79
|
i++
|
|
69
80
|
break
|
|
70
81
|
}
|
|
82
|
+
|
|
71
83
|
str += ss(args[a])
|
|
72
84
|
lastPos = i + 2
|
|
73
85
|
i++
|
|
74
86
|
break
|
|
75
87
|
case 115: // 's'
|
|
76
88
|
if (a >= argumentLength) { break }
|
|
77
|
-
if (lastPos < i) {
|
|
89
|
+
if (lastPos < i) {
|
|
90
|
+
str += f.slice(lastPos, i)
|
|
91
|
+
}
|
|
78
92
|
str += String(args[a])
|
|
79
93
|
lastPos = i + 2
|
|
80
94
|
i++
|
package/lib/metrics/constants.js
CHANGED
|
@@ -29,7 +29,7 @@ exports.TRANSPORTER_PACKETS_RECEIVED = 'weave.transport.packets.received'
|
|
|
29
29
|
exports.TRANSPORT_IN_FLIGHT_STREAMS = 'weave.transport.streams.in-flight'
|
|
30
30
|
|
|
31
31
|
// Bulkhead
|
|
32
|
-
exports.
|
|
32
|
+
exports.BULKHEAD_REQUESTS_IN_FLIGHT = 'weave.bulkhead.requests.in-flight'
|
|
33
33
|
|
|
34
34
|
// OS Metrics
|
|
35
35
|
exports.OS_HOSTNAME = 'os.hostname'
|
|
@@ -50,8 +50,10 @@ exports.OS_CPU_LOAD_1 = 'os.cpu-load.1'
|
|
|
50
50
|
exports.OS_CPU_LOAD_5 = 'os.cpu-load.5'
|
|
51
51
|
exports.OS_CPU_LOAD_15 = 'os.cpu-load.15'
|
|
52
52
|
|
|
53
|
-
//
|
|
54
|
-
exports.
|
|
55
|
-
exports.
|
|
56
|
-
exports.
|
|
57
|
-
exports.
|
|
53
|
+
// Cache
|
|
54
|
+
exports.CACHE_GET_TOTAL = 'weave.cache.items.get'
|
|
55
|
+
exports.CACHE_SET_TOTAL = 'weave.cache.items.set'
|
|
56
|
+
exports.CACHE_DELETED_TOTAL = 'weave.cache.items.deleted'
|
|
57
|
+
exports.CACHE_FOUND_TOTAL = 'weave.cache.items.found'
|
|
58
|
+
exports.CACHE_CLEANED_TOTAL = 'weave.cache.items.cleaned'
|
|
59
|
+
exports.CACHE_EXPIRED_TOTAL = 'weave.cache.items.expired'
|
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Author: Kevin Ries (kevin@fachw3rk.de)
|
|
3
3
|
* -----
|
|
4
|
-
* Copyright
|
|
4
|
+
* Copyright 2021 Fachwerk
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
function callHook (hook, service, context, result) {
|
|
8
8
|
if (typeof hook === 'function') {
|
|
9
9
|
return hook.call(service, context, result)
|
|
10
10
|
} else if (Array.isArray(hook)) {
|
|
11
|
-
return hook.reduce(
|
|
11
|
+
return hook.reduce(
|
|
12
|
+
(promise, fn) => promise.then(res => fn.call(service, context, res)),
|
|
13
|
+
Promise.resolve(result))
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function callErrorHook (hook, service, context, error) {
|
|
18
|
+
if (typeof hook === 'function') {
|
|
19
|
+
return hook.call(service, context, error)
|
|
20
|
+
} else if (Array.isArray(hook)) {
|
|
21
|
+
return hook.reduce(
|
|
22
|
+
(promise, fn) => promise.catch(err => fn.call(service, context, err)),
|
|
23
|
+
Promise.reject(error))
|
|
12
24
|
}
|
|
13
25
|
}
|
|
14
26
|
|
|
@@ -19,6 +31,7 @@ function sanitizeHooks (hooks, service) {
|
|
|
19
31
|
|
|
20
32
|
if (Array.isArray(hooks)) {
|
|
21
33
|
return hooks.map((hook) => {
|
|
34
|
+
// resolve the method name
|
|
22
35
|
if (typeof hook === 'string') {
|
|
23
36
|
return (service && typeof service[hook] === 'function') ? service[hook] : null
|
|
24
37
|
}
|
|
@@ -32,16 +45,34 @@ const makeActionHookMiddleware = function (handler, action) {
|
|
|
32
45
|
const name = action.shortName
|
|
33
46
|
const hooks = (action.service && action.service.schema) ? action.service.schema.hooks : null
|
|
34
47
|
|
|
35
|
-
if (hooks) {
|
|
36
|
-
|
|
37
|
-
const
|
|
38
|
-
const
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
48
|
+
if (hooks || action.hooks) {
|
|
49
|
+
// Wildcard hooks
|
|
50
|
+
const beforeWildcardHook = hooks && hooks.before ? sanitizeHooks(hooks.before['*'], action.service) : null
|
|
51
|
+
const afterWildcardHook = hooks && hooks.after ? sanitizeHooks(hooks.after['*'], action.service) : null
|
|
52
|
+
const errorWildcardHook = hooks && hooks.error ? sanitizeHooks(hooks.error['*'], action.service) : null
|
|
53
|
+
|
|
54
|
+
// Action name-related hooks
|
|
55
|
+
const beforeHook = hooks && hooks.before ? sanitizeHooks(hooks.before[name], action.service) : null
|
|
56
|
+
const afterHook = hooks && hooks.after ? sanitizeHooks(hooks.after[name], action.service) : null
|
|
57
|
+
const errorHook = hooks && hooks.error ? sanitizeHooks(hooks.error[name], action.service) : null
|
|
42
58
|
|
|
43
|
-
|
|
44
|
-
|
|
59
|
+
// Hooks in action definition
|
|
60
|
+
const actionBeforeHook = action.hooks && action.hooks.before ? sanitizeHooks(action.hooks.before, action.service) : null
|
|
61
|
+
const actionAfterHook = action.hooks && action.hooks.after ? sanitizeHooks(action.hooks.after, action.service) : null
|
|
62
|
+
const actionErrorHook = action.hooks && action.hooks.error ? sanitizeHooks(action.hooks.error, action.service) : null
|
|
63
|
+
|
|
64
|
+
if (
|
|
65
|
+
beforeWildcardHook ||
|
|
66
|
+
afterWildcardHook ||
|
|
67
|
+
errorWildcardHook ||
|
|
68
|
+
beforeHook ||
|
|
69
|
+
afterHook ||
|
|
70
|
+
errorHook ||
|
|
71
|
+
actionBeforeHook ||
|
|
72
|
+
actionAfterHook ||
|
|
73
|
+
actionErrorHook
|
|
74
|
+
) {
|
|
75
|
+
return function actionHookMiddleware (context, serviceInjections) {
|
|
45
76
|
let promise = Promise.resolve()
|
|
46
77
|
|
|
47
78
|
// before all hook
|
|
@@ -54,8 +85,18 @@ const makeActionHookMiddleware = function (handler, action) {
|
|
|
54
85
|
promise = promise.then(() => callHook(beforeHook, action.service, context))
|
|
55
86
|
}
|
|
56
87
|
|
|
88
|
+
// Before hook
|
|
89
|
+
if (actionBeforeHook) {
|
|
90
|
+
promise = promise.then(() => callHook(actionBeforeHook, action.service, context))
|
|
91
|
+
}
|
|
92
|
+
|
|
57
93
|
// Call action handler
|
|
58
|
-
promise = promise.then(() => handler(context))
|
|
94
|
+
promise = promise.then(() => handler(context, serviceInjections))
|
|
95
|
+
|
|
96
|
+
// After hook in action definition
|
|
97
|
+
if (actionAfterHook) {
|
|
98
|
+
promise = promise.then(result => callHook(actionAfterHook, action.service, context, result))
|
|
99
|
+
}
|
|
59
100
|
|
|
60
101
|
// After hook
|
|
61
102
|
if (afterHook) {
|
|
@@ -67,13 +108,20 @@ const makeActionHookMiddleware = function (handler, action) {
|
|
|
67
108
|
promise = promise.then(result => callHook(afterWildcardHook, action.service, context, result))
|
|
68
109
|
}
|
|
69
110
|
|
|
111
|
+
// Error hooks
|
|
112
|
+
// Error hook in action definition
|
|
113
|
+
if (actionErrorHook) {
|
|
114
|
+
promise = promise.catch(error => callErrorHook(actionErrorHook, action.service, context, error))
|
|
115
|
+
}
|
|
116
|
+
|
|
70
117
|
// Error hook
|
|
71
118
|
if (errorHook) {
|
|
72
|
-
promise = promise.catch(error =>
|
|
119
|
+
promise = promise.catch(error => callErrorHook(errorHook, action.service, context, error))
|
|
73
120
|
}
|
|
121
|
+
|
|
74
122
|
// Error wildcard hook
|
|
75
123
|
if (errorWildcardHook) {
|
|
76
|
-
promise = promise.catch(error =>
|
|
124
|
+
promise = promise.catch(error => callErrorHook(errorWildcardHook, action.service, context, error))
|
|
77
125
|
}
|
|
78
126
|
|
|
79
127
|
return promise
|
|
@@ -1,9 +1,9 @@
|
|
|
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 { WeaveQueueSizeExceededError } = require('../../errors')
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -44,11 +44,11 @@ module.exports = (runtime) => {
|
|
|
44
44
|
})
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
return function bulkheadMiddlware (context) {
|
|
47
|
+
return function bulkheadMiddlware (context, serviceInjections) {
|
|
48
48
|
// Execute action immediately
|
|
49
49
|
if (currentlyInFlight < bulkheadOptions.concurrentCalls) {
|
|
50
50
|
currentlyInFlight++
|
|
51
|
-
return handler(context)
|
|
51
|
+
return handler(context, serviceInjections)
|
|
52
52
|
.then(result => {
|
|
53
53
|
currentlyInFlight--
|
|
54
54
|
callNext()
|
|
@@ -81,6 +81,7 @@ module.exports = (runtime) => {
|
|
|
81
81
|
created () {
|
|
82
82
|
if (runtime.options.metrics.enabled) {
|
|
83
83
|
// todo: add bulkhead metrics
|
|
84
|
+
runtime.metrics.register({ type: 'gauge', name: Constants.BULKHEAD_REQUESTS_IN_FLIGHT, description: 'Number of in flight requests.' })
|
|
84
85
|
}
|
|
85
86
|
},
|
|
86
87
|
localAction: wrapBulkheadMiddleware
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const { isObject } = require('@weave-js/utils')
|
|
2
|
+
|
|
3
|
+
module.exports = (runtime) => {
|
|
4
|
+
return {
|
|
5
|
+
localAction: (handler, action) => {
|
|
6
|
+
const cacheOptions = Object.assign(
|
|
7
|
+
isObject(action.cache) ? action.cache : { enabled: !!action.cache },
|
|
8
|
+
runtime.options.cache
|
|
9
|
+
)
|
|
10
|
+
if (cacheOptions.enabled) {
|
|
11
|
+
return function cacheMiddleware (context, serviceInjections) {
|
|
12
|
+
const cache = runtime.cache
|
|
13
|
+
const cacheHashKey = cache.getCachingHash(action.name, context.data, context.meta, action.cache.keys)
|
|
14
|
+
context.isCachedResult = false
|
|
15
|
+
|
|
16
|
+
if (context.meta.$noCache === true) {
|
|
17
|
+
return handler(context, serviceInjections)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (cache.isConnected === false) {
|
|
21
|
+
cache.log('Cache adapter is not connected yet. Call handler...')
|
|
22
|
+
return handler(context, serviceInjections)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (cacheOptions.lock.enabled) {
|
|
26
|
+
let cacheProm
|
|
27
|
+
if (cacheOptions.lock.staleTime && cache.getWithTTl) {
|
|
28
|
+
|
|
29
|
+
} else {
|
|
30
|
+
cacheProm = runtime.cache.get(cacheHashKey)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return cacheProm.then((cachedResult) => {
|
|
34
|
+
if (cachedResult !== null) {
|
|
35
|
+
// Found a cached value. Skip calling handler and return our value
|
|
36
|
+
context.isCachedResult = true
|
|
37
|
+
return cachedResult
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return cache.lock(cacheHashKey).then((release) => {
|
|
41
|
+
return cache.get(cacheHashKey).then(cachedResult => {
|
|
42
|
+
if (cachedResult !== null) {
|
|
43
|
+
// Found a cached value. Skip calling handler and return our value
|
|
44
|
+
context.isCachedResult = true
|
|
45
|
+
return release().then(() => {
|
|
46
|
+
return cachedResult
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return handler(context).then((result) => {
|
|
51
|
+
// Cache the value
|
|
52
|
+
cache.set(cacheHashKey, result, action.cache.ttl).then(() => {
|
|
53
|
+
// release the lock
|
|
54
|
+
release()
|
|
55
|
+
})
|
|
56
|
+
return result
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Not using cache lock
|
|
64
|
+
return runtime.cache.get(cacheHashKey).then((cachedResult) => {
|
|
65
|
+
if (cachedResult !== null) {
|
|
66
|
+
context.isCachedResult = true
|
|
67
|
+
return cachedResult
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return handler(context, serviceInjections).then((result) => {
|
|
71
|
+
runtime.cache.set(cacheHashKey, result, action.cache.ttl)
|
|
72
|
+
return result
|
|
73
|
+
})
|
|
74
|
+
})
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return handler
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|