@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.
Files changed (98) hide show
  1. package/lib/ExtendableError.js +33 -0
  2. package/lib/broker/context.js +25 -13
  3. package/lib/broker/{default-options.js → defaultOptions.js} +23 -5
  4. package/lib/broker/index.js +224 -194
  5. package/lib/buildRuntime.js +70 -0
  6. package/lib/cache/base.js +47 -31
  7. package/lib/cache/inMemory.js +140 -0
  8. package/lib/cache/index.js +2 -2
  9. package/lib/cache/lock.js +21 -4
  10. package/lib/constants.js +8 -5
  11. package/lib/errorHandler.js +19 -0
  12. package/lib/errors.js +17 -10
  13. package/lib/helper/{define-action.js → defineAction.js} +3 -1
  14. package/lib/helper/{define-broker-options.js → defineBrokerOptions.js} +2 -0
  15. package/lib/helper/{define-service.js → defineService.js} +4 -1
  16. package/lib/index.js +15 -89
  17. package/lib/logger/base.js +3 -3
  18. package/lib/logger/format/asHumanReadable.js +42 -0
  19. package/lib/logger/format/asJson.js +25 -0
  20. package/lib/logger/format/index.js +4 -0
  21. package/lib/logger/index.js +12 -5
  22. package/lib/logger/levels.js +9 -8
  23. package/lib/logger/tools.js +4 -25
  24. package/lib/logger/utils/colorize.js +32 -0
  25. package/lib/logger/utils/format.js +18 -4
  26. package/lib/metrics/constants.js +8 -6
  27. package/lib/metrics/types/gauge.js +1 -1
  28. package/lib/middlewares/action-hooks/index.js +62 -14
  29. package/lib/middlewares/bulkhead/index.js +5 -4
  30. package/lib/middlewares/cache/index.js +80 -0
  31. package/lib/middlewares/circuit-breaker/index.js +41 -16
  32. package/lib/middlewares/context-tracker/index.js +3 -3
  33. package/lib/middlewares/error-handler/index.js +3 -3
  34. package/lib/middlewares/index.js +2 -1
  35. package/lib/middlewares/metrics/getMiddlewareWrapper.js +2 -2
  36. package/lib/middlewares/metrics/index.js +2 -2
  37. package/lib/middlewares/retry/index.js +11 -10
  38. package/lib/middlewares/timeout/index.js +5 -5
  39. package/lib/middlewares/tracing/index.js +27 -14
  40. package/lib/middlewares/tracing/tags.js +43 -0
  41. package/lib/middlewares/validator/index.js +6 -6
  42. package/lib/registry/{action-endpoint.js → actionEndpoint.js} +0 -0
  43. package/lib/registry/collections/{action-collection.js → actionCollection.js} +2 -2
  44. package/lib/registry/collections/{endpoint-collection.js → endpointCollection.js} +19 -3
  45. package/lib/registry/collections/{event-collection.js → eventCollection.js} +15 -9
  46. package/lib/registry/collections/{node-collection.js → nodeCollection.js} +1 -1
  47. package/lib/registry/collections/{service-collection.js → serviceCollection.js} +2 -2
  48. package/lib/registry/{event-endpoint.js → eventEndpoint.js} +1 -1
  49. package/lib/registry/node.js +1 -1
  50. package/lib/registry/registry.js +10 -23
  51. package/lib/registry/service/service.js +2 -2
  52. package/lib/registry/{service-item.js → serviceItem.js} +1 -1
  53. package/lib/runtime/{init-action-invoker.js → initActionInvoker.js} +3 -3
  54. package/lib/runtime/{init-cache.js → initCache.js} +0 -0
  55. package/lib/runtime/{init-context-factory.js → initContextFactory.js} +2 -2
  56. package/lib/runtime/{init-eventbus.js → initEventbus.js} +11 -10
  57. package/lib/runtime/{init-logger.js → initLogger.js} +0 -0
  58. package/lib/runtime/{init-metrics.js → initMetrics.js} +11 -10
  59. package/lib/runtime/{init-middleware-manager.js → initMiddlewareManager.js} +1 -1
  60. package/lib/runtime/{init-registry.js → initRegistry.js} +1 -1
  61. package/lib/runtime/{init-service-manager.js → initServiceManager.js} +0 -0
  62. package/lib/runtime/{init-tracing.js → initTracing.js} +2 -1
  63. package/lib/runtime/{init-transport.js → initTransport.js} +1 -1
  64. package/lib/runtime/{init-uuid-factory.js → initUuidFactory.js} +0 -0
  65. package/lib/runtime/{init-validator.js → initValidator.js} +1 -1
  66. package/lib/tracing/collectors/base.js +11 -19
  67. package/lib/tracing/collectors/event.js +2 -2
  68. package/lib/tracing/collectors/index.js +2 -2
  69. package/lib/tracing/span.js +8 -6
  70. package/lib/transport/InboundTransformStream.js +75 -0
  71. package/lib/transport/adapters/{adapter-base.js → adapteBase.js} +16 -1
  72. package/lib/transport/adapters/adapters.js +1 -1
  73. package/lib/transport/adapters/dummy/index.js +3 -3
  74. package/lib/transport/adapters/index.js +1 -1
  75. package/lib/transport/adapters/tcp/discovery/index.js +45 -31
  76. package/lib/transport/adapters/tcp/index.js +20 -13
  77. package/lib/transport/adapters/tcp/tcpReader.js +1 -0
  78. package/lib/transport/adapters/tcp/tcpWriteStream.js +1 -1
  79. package/lib/transport/adapters/tcp/tcpWriter.js +2 -2
  80. package/lib/transport/createMessage.js +11 -0
  81. package/lib/transport/{transport-factory.js → createTransport.js} +234 -173
  82. package/lib/transport/errorPayloadFactory.js +18 -0
  83. package/lib/transport/{message-handlers.js → messageHandlers.js} +93 -24
  84. package/lib/transport/messageTypes.js +23 -0
  85. package/lib/types.js +66 -66
  86. package/lib/utils/index.js +0 -1
  87. package/lib/utils/options.js +4 -2
  88. package/lib/utils/{restore-error.js → restoreError.js} +1 -1
  89. package/package.json +6 -12
  90. package/CHANGELOG.md +0 -1293
  91. package/lib/cache/memory.js +0 -91
  92. package/lib/middlewares/tracing/buildTags.js +0 -17
  93. package/lib/new-errors.js +0 -25
  94. package/lib/tracing/collectors/console.js +0 -34
  95. package/lib/tracing/index.js +0 -3
  96. package/lib/tracing/tracer.js +0 -64
  97. package/lib/transport/message-types.js +0 -59
  98. package/lib/transport/message.js +0 -16
@@ -1,5 +1,5 @@
1
1
  const { isStandardLevel, levelMethods } = require('./levels')
2
- const { noop, generateLogMethod, asJsonString } = require('./tools')
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 > values[key]) {
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 = asJsonString(runtime, object, message, number, time)
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
+ }
@@ -0,0 +1,4 @@
1
+ const { asJson } = require('./asJson')
2
+ const { asHumanReadable } = require('./asHumanReadable')
3
+
4
+ module.exports = { asJson, asHumanReadable }
@@ -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: { pid, hostname },
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
- Object.assign(runtime, {
58
- levels
59
- })
65
+ // merge levels in logger runtime
66
+ Object.assign(runtime, { levels })
60
67
 
61
68
  initBase(runtime)
62
69
 
@@ -1,14 +1,15 @@
1
1
  const { generateLogMethod } = require('./tools')
2
2
 
3
3
  const levels = {
4
- verbose: 10,
5
- debug: 20,
6
- info: 30,
7
- warn: 40,
8
- error: 50,
9
- fatal: 60
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: Infinity }}),
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
-
@@ -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) { break }
56
- if (lastPos < i) { str += f.slice(lastPos, i) }
57
- if (args[a] === undefined) break
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) { str += f.slice(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++
@@ -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.REQUESTS_BULKHEAD_IN_FLIGHT = 'weave.requests.bulkhead.in-flight'
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
- // Metric types
54
- exports.TYPE_INFO = 'info'
55
- exports.TYPE_GAUGE = 'gauge'
56
- exports.TYPE_COUNTER = 'counter'
57
- exports.TYPE_HISTOGRAM = 'counter'
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'
@@ -6,7 +6,7 @@ exports.createGauge = (registry, obj) => {
6
6
  base.value = 0
7
7
 
8
8
  base.increment = (labels, value, timestamp) => {
9
- const item = base.values.get(labels)
9
+ const item = base.get(labels)
10
10
  base.set((item ? item.value : 0) + value, labels, timestamp)
11
11
  }
12
12
 
@@ -1,14 +1,26 @@
1
1
  /*
2
2
  * Author: Kevin Ries (kevin@fachw3rk.de)
3
3
  * -----
4
- * Copyright 2020 Fachwerk
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((promise, fn) => promise.then(res => fn.call(service, context, res)), Promise.resolve(result))
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
- const beforeWildcardHook = hooks.before ? sanitizeHooks(hooks.before['*'], action.service) : null
37
- const afterWildcardHook = hooks.after ? sanitizeHooks(hooks.after['*'], action.service) : null
38
- const errorWildcardHook = hooks.error ? sanitizeHooks(hooks.error['*'], action.service) : null
39
- const beforeHook = hooks.before ? sanitizeHooks(hooks.before[name], action.service) : null
40
- const afterHook = hooks.after ? sanitizeHooks(hooks.after[name], action.service) : null
41
- const errorHook = hooks.error ? sanitizeHooks(hooks.error[name], action.service) : null
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
- if (beforeWildcardHook || afterWildcardHook || errorWildcardHook || beforeHook || afterHook || errorHook) {
44
- return function actionHookMiddleware (context) {
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 => callHook(errorHook, action.service, context, 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 => callHook(errorWildcardHook, action.service, context, 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 2020 Fachwerk
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
+ }