@weave-js/core 0.11.1 → 0.12.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 (116) hide show
  1. package/.eslintrc.js +1 -1
  2. package/jest.config.js +1 -1
  3. package/lib/ExtendableError.js +7 -7
  4. package/lib/broker/context.js +49 -49
  5. package/lib/broker/defaultOptions.js +8 -9
  6. package/lib/broker/index.js +160 -164
  7. package/lib/buildRuntime.js +34 -34
  8. package/lib/cache/adapters/base.js +50 -74
  9. package/lib/cache/adapters/inMemory.js +58 -58
  10. package/lib/cache/adapters/inMemoryLru.js +57 -57
  11. package/lib/cache/adapters/index.js +3 -39
  12. package/lib/cache/getCacheKeyByObject.js +31 -0
  13. package/lib/cache/getPropertyFromDataOrMetadata.js +20 -0
  14. package/lib/cache/lock.js +30 -24
  15. package/lib/constants.js +5 -5
  16. package/lib/errorHandler.js +8 -8
  17. package/lib/errors.js +35 -35
  18. package/lib/helper/defineAction.js +2 -2
  19. package/lib/helper/defineBrokerOptions.js +2 -2
  20. package/lib/helper/defineService.js +2 -2
  21. package/lib/index.js +21 -21
  22. package/lib/logger/base.js +38 -29
  23. package/lib/logger/format/asHumanReadable.js +15 -15
  24. package/lib/logger/format/asJson.js +10 -10
  25. package/lib/logger/format/index.js +3 -3
  26. package/lib/logger/index.js +24 -24
  27. package/lib/logger/levels.js +21 -21
  28. package/lib/logger/tools.js +15 -15
  29. package/lib/logger/utils/colorize.js +23 -23
  30. package/lib/logger/utils/format.js +75 -65
  31. package/lib/metrics/common.js +47 -47
  32. package/lib/metrics/constants.js +44 -44
  33. package/lib/metrics/exporter/base.js +8 -8
  34. package/lib/metrics/exporter/event.js +20 -20
  35. package/lib/metrics/exporter/index.js +15 -15
  36. package/lib/metrics/index.js +2 -2
  37. package/lib/metrics/types/base.js +20 -20
  38. package/lib/metrics/types/counter.js +6 -6
  39. package/lib/metrics/types/gauge.js +24 -24
  40. package/lib/metrics/types/histogram.js +26 -26
  41. package/lib/metrics/types/index.js +6 -6
  42. package/lib/metrics/types/info.js +17 -17
  43. package/lib/middlewares/action-hooks/index.js +38 -38
  44. package/lib/middlewares/bulkhead/index.js +34 -34
  45. package/lib/middlewares/cache/index.js +37 -37
  46. package/lib/middlewares/circuit-breaker/index.js +62 -62
  47. package/lib/middlewares/context-tracker/index.js +39 -39
  48. package/lib/middlewares/error-handler/index.js +14 -14
  49. package/lib/middlewares/index.js +2 -2
  50. package/lib/middlewares/metrics/getMiddlewareWrapper.js +17 -17
  51. package/lib/middlewares/metrics/index.js +29 -29
  52. package/lib/middlewares/retry/index.js +15 -15
  53. package/lib/middlewares/timeout/index.js +16 -16
  54. package/lib/middlewares/tracing/index.js +37 -37
  55. package/lib/middlewares/tracing/tags.js +6 -6
  56. package/lib/middlewares/validator/index.js +31 -31
  57. package/lib/registry/actionEndpoint.js +8 -8
  58. package/lib/registry/collections/actionCollection.js +39 -35
  59. package/lib/registry/collections/endpointCollection.js +63 -63
  60. package/lib/registry/collections/eventCollection.js +62 -62
  61. package/lib/registry/collections/nodeCollection.js +45 -45
  62. package/lib/registry/collections/serviceCollection.js +61 -55
  63. package/lib/registry/eventEndpoint.js +14 -14
  64. package/lib/registry/load-balancer/base.js +3 -3
  65. package/lib/registry/load-balancer/index.js +7 -7
  66. package/lib/registry/node.js +27 -27
  67. package/lib/registry/registry.js +139 -136
  68. package/lib/registry/service/parseAction.js +16 -16
  69. package/lib/registry/service/parseEvent.js +18 -18
  70. package/lib/registry/service/reduceMixins.js +10 -10
  71. package/lib/registry/service/service.js +72 -72
  72. package/lib/registry/serviceItem.js +21 -21
  73. package/lib/runtime/initActionInvoker.js +21 -21
  74. package/lib/runtime/initCache.js +7 -7
  75. package/lib/runtime/initContextFactory.js +22 -22
  76. package/lib/runtime/initEventbus.js +49 -49
  77. package/lib/runtime/initLogger.js +11 -11
  78. package/lib/runtime/initMetrics.js +54 -54
  79. package/lib/runtime/initMiddlewareManager.js +21 -21
  80. package/lib/runtime/initRegistry.js +6 -6
  81. package/lib/runtime/initServiceManager.js +85 -68
  82. package/lib/runtime/initTracing.js +23 -23
  83. package/lib/runtime/initTransport.js +5 -5
  84. package/lib/runtime/initUuidFactory.js +4 -4
  85. package/lib/runtime/initValidator.js +5 -5
  86. package/lib/tracing/collectors/base.js +22 -22
  87. package/lib/tracing/collectors/event.js +33 -33
  88. package/lib/tracing/collectors/index.js +15 -15
  89. package/lib/tracing/span.js +26 -26
  90. package/lib/tracing/time.js +8 -8
  91. package/lib/transport/InboundTransformStream.js +26 -26
  92. package/lib/transport/adapters/adapteBase.js +30 -30
  93. package/lib/transport/adapters/adapters.js +4 -4
  94. package/lib/transport/adapters/dummy/index.js +18 -18
  95. package/lib/transport/adapters/fromURI.js +13 -13
  96. package/lib/transport/adapters/getAdapterByName.js +5 -5
  97. package/lib/transport/adapters/index.js +12 -12
  98. package/lib/transport/adapters/tcp/discovery/codec.js +4 -4
  99. package/lib/transport/adapters/tcp/discovery/index.js +62 -62
  100. package/lib/transport/adapters/tcp/index.js +169 -171
  101. package/lib/transport/adapters/tcp/tcp-messagetypes.js +7 -7
  102. package/lib/transport/adapters/tcp/tcpReader.js +39 -39
  103. package/lib/transport/adapters/tcp/tcpWriteStream.js +26 -26
  104. package/lib/transport/adapters/tcp/tcpWriter.js +57 -57
  105. package/lib/transport/adapters/tcp/utils.js +12 -12
  106. package/lib/transport/createMessage.js +4 -4
  107. package/lib/transport/createTransport.js +254 -254
  108. package/lib/transport/errorPayloadFactory.js +14 -17
  109. package/lib/transport/messageHandlers.js +200 -200
  110. package/lib/transport/messageTypes.js +19 -19
  111. package/lib/types.js +28 -15
  112. package/lib/utils/index.js +1 -1
  113. package/lib/utils/options.js +44 -44
  114. package/lib/utils/restoreError.js +4 -4
  115. package/package.json +4 -4
  116. package/lib/cache/base.js +0 -136
@@ -1,65 +1,65 @@
1
1
  /*
2
- * Author: Kevin Ries (kevin@fachw3rk.de)
2
+ * Author: Kevin Ries (kevin.ries@fachwerk.io)
3
3
  * -----
4
4
  * Copyright 2021 Fachwerk
5
5
  */
6
6
 
7
7
  function callHook (hook, service, context, result) {
8
8
  if (typeof hook === 'function') {
9
- return hook.call(service, context, result)
9
+ return hook.call(service, context, result);
10
10
  } else if (Array.isArray(hook)) {
11
11
  return hook.reduce(
12
12
  (promise, fn) => promise.then(res => fn.call(service, context, res)),
13
- Promise.resolve(result))
13
+ Promise.resolve(result));
14
14
  }
15
15
  }
16
16
 
17
17
  function callErrorHook (hook, service, context, error) {
18
18
  if (typeof hook === 'function') {
19
- return hook.call(service, context, error)
19
+ return hook.call(service, context, error);
20
20
  } else if (Array.isArray(hook)) {
21
21
  return hook.reduce(
22
22
  (promise, fn) => promise.catch(err => fn.call(service, context, err)),
23
- Promise.reject(error))
23
+ Promise.reject(error));
24
24
  }
25
25
  }
26
26
 
27
27
  function sanitizeHooks (hooks, service) {
28
28
  if (typeof hooks === 'string') {
29
- hooks = hooks.split(' ')
29
+ hooks = hooks.split(' ');
30
30
  }
31
31
 
32
32
  if (Array.isArray(hooks)) {
33
33
  return hooks.map((hook) => {
34
34
  // resolve the method name
35
35
  if (typeof hook === 'string') {
36
- return (service && typeof service[hook] === 'function') ? service[hook] : null
36
+ return (service && typeof service[hook] === 'function') ? service[hook] : null;
37
37
  }
38
- return hook
39
- })
38
+ return hook;
39
+ });
40
40
  }
41
- return hooks
41
+ return hooks;
42
42
  }
43
43
 
44
44
  const makeActionHookMiddleware = function (handler, action) {
45
- const name = action.shortName
46
- const hooks = (action.service && action.service.schema) ? action.service.schema.hooks : null
45
+ const name = action.shortName;
46
+ const hooks = (action.service && action.service.schema) ? action.service.schema.hooks : null;
47
47
 
48
48
  if (hooks || action.hooks) {
49
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
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
53
 
54
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
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;
58
58
 
59
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
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
63
 
64
64
  if (
65
65
  beforeWildcardHook ||
@@ -73,66 +73,66 @@ const makeActionHookMiddleware = function (handler, action) {
73
73
  actionErrorHook
74
74
  ) {
75
75
  return function actionHookMiddleware (context, serviceInjections) {
76
- let promise = Promise.resolve()
76
+ let promise = Promise.resolve();
77
77
 
78
78
  // before all hook
79
79
  if (beforeWildcardHook) {
80
- promise = promise.then(() => callHook(beforeWildcardHook, action.service, context))
80
+ promise = promise.then(() => callHook(beforeWildcardHook, action.service, context));
81
81
  }
82
82
 
83
83
  // Before hook
84
84
  if (beforeHook) {
85
- promise = promise.then(() => callHook(beforeHook, action.service, context))
85
+ promise = promise.then(() => callHook(beforeHook, action.service, context));
86
86
  }
87
87
 
88
88
  // Before hook
89
89
  if (actionBeforeHook) {
90
- promise = promise.then(() => callHook(actionBeforeHook, action.service, context))
90
+ promise = promise.then(() => callHook(actionBeforeHook, action.service, context));
91
91
  }
92
92
 
93
93
  // Call action handler
94
- promise = promise.then(() => handler(context, serviceInjections))
94
+ promise = promise.then(() => handler(context, serviceInjections));
95
95
 
96
96
  // After hook in action definition
97
97
  if (actionAfterHook) {
98
- promise = promise.then(result => callHook(actionAfterHook, action.service, context, result))
98
+ promise = promise.then(result => callHook(actionAfterHook, action.service, context, result));
99
99
  }
100
100
 
101
101
  // After hook
102
102
  if (afterHook) {
103
- promise = promise.then(result => callHook(afterHook, action.service, context, result))
103
+ promise = promise.then(result => callHook(afterHook, action.service, context, result));
104
104
  }
105
105
 
106
106
  // After wildcard hook
107
107
  if (afterWildcardHook) {
108
- promise = promise.then(result => callHook(afterWildcardHook, action.service, context, result))
108
+ promise = promise.then(result => callHook(afterWildcardHook, action.service, context, result));
109
109
  }
110
110
 
111
111
  // Error hooks
112
112
  // Error hook in action definition
113
113
  if (actionErrorHook) {
114
- promise = promise.catch(error => callErrorHook(actionErrorHook, action.service, context, error))
114
+ promise = promise.catch(error => callErrorHook(actionErrorHook, action.service, context, error));
115
115
  }
116
116
 
117
117
  // Error hook
118
118
  if (errorHook) {
119
- promise = promise.catch(error => callErrorHook(errorHook, action.service, context, error))
119
+ promise = promise.catch(error => callErrorHook(errorHook, action.service, context, error));
120
120
  }
121
121
 
122
122
  // Error wildcard hook
123
123
  if (errorWildcardHook) {
124
- promise = promise.catch(error => callErrorHook(errorWildcardHook, action.service, context, error))
124
+ promise = promise.catch(error => callErrorHook(errorWildcardHook, action.service, context, error));
125
125
  }
126
126
 
127
- return promise
128
- }
127
+ return promise;
128
+ };
129
129
  }
130
130
  }
131
- return handler
132
- }
131
+ return handler;
132
+ };
133
133
 
134
134
  module.exports = () => {
135
135
  return {
136
136
  localAction: makeActionHookMiddleware
137
- }
138
- }
137
+ };
138
+ };
@@ -1,10 +1,10 @@
1
1
  /*
2
- * Author: Kevin Ries (kevin@fachw3rk.de)
2
+ * Author: Kevin Ries (kevin.ries@fachwerk.io)
3
3
  * -----
4
4
  * Copyright 2021 Fachwerk
5
5
  */
6
- const { Constants } = require('../../metrics')
7
- const { WeaveQueueSizeExceededError } = require('../../errors')
6
+ const { Constants } = require('../../metrics');
7
+ const { WeaveQueueSizeExceededError } = require('../../errors');
8
8
 
9
9
  /**
10
10
  * @typedef {import('../../types').Runtime} Runtime
@@ -18,47 +18,47 @@ const { WeaveQueueSizeExceededError } = require('../../errors')
18
18
  */
19
19
  module.exports = (runtime) => {
20
20
  const wrapBulkheadMiddleware = function (handler, action) {
21
- const bulkheadOptions = runtime.options.bulkhead
21
+ const bulkheadOptions = runtime.options.bulkhead;
22
22
 
23
23
  if (bulkheadOptions.enabled) {
24
- const queue = []
25
- let currentlyInFlight = 0
24
+ const queue = [];
25
+ let currentlyInFlight = 0;
26
26
 
27
27
  const callNext = () => {
28
- if (queue.length === 0) return
29
- if (currentlyInFlight >= bulkheadOptions.concurrentCalls) return
28
+ if (queue.length === 0) return;
29
+ if (currentlyInFlight >= bulkheadOptions.concurrentCalls) return;
30
30
 
31
- const item = queue.shift()
31
+ const item = queue.shift();
32
32
 
33
- currentlyInFlight++
33
+ currentlyInFlight++;
34
34
  handler(item.context)
35
35
  .then(result => {
36
- currentlyInFlight--
37
- item.resolve(result)
38
- callNext()
36
+ currentlyInFlight--;
37
+ item.resolve(result);
38
+ callNext();
39
39
  })
40
40
  .catch(error => {
41
- currentlyInFlight--
42
- callNext()
43
- return item.reject(error)
44
- })
45
- }
41
+ currentlyInFlight--;
42
+ callNext();
43
+ return item.reject(error);
44
+ });
45
+ };
46
46
 
47
47
  return function bulkheadMiddlware (context, serviceInjections) {
48
48
  // Execute action immediately
49
49
  if (currentlyInFlight < bulkheadOptions.concurrentCalls) {
50
- currentlyInFlight++
50
+ currentlyInFlight++;
51
51
  return handler(context, serviceInjections)
52
52
  .then(result => {
53
- currentlyInFlight--
54
- callNext()
55
- return result
53
+ currentlyInFlight--;
54
+ callNext();
55
+ return result;
56
56
  })
57
57
  .catch(error => {
58
- currentlyInFlight--
59
- callNext()
60
- return Promise.reject(error)
61
- })
58
+ currentlyInFlight--;
59
+ callNext();
60
+ return Promise.reject(error);
61
+ });
62
62
  }
63
63
 
64
64
  // Reject the action if the max queue size is reached.
@@ -67,23 +67,23 @@ module.exports = (runtime) => {
67
67
  action: action.name,
68
68
  limit: bulkheadOptions.maxQueueSize,
69
69
  size: queue.length
70
- }))
70
+ }));
71
71
  }
72
72
 
73
73
  // Queue the request
74
- return new Promise((resolve, reject) => queue.push({ resolve, reject, context }))
75
- }
74
+ return new Promise((resolve, reject) => queue.push({ resolve, reject, context }));
75
+ };
76
76
  }
77
- return handler
78
- }
77
+ return handler;
78
+ };
79
79
 
80
80
  return {
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
+ runtime.metrics.register({ type: 'gauge', name: Constants.BULKHEAD_REQUESTS_IN_FLIGHT, description: 'Number of in flight requests.' });
85
85
  }
86
86
  },
87
87
  localAction: wrapBulkheadMiddleware
88
- }
89
- }
88
+ };
89
+ };
@@ -1,29 +1,29 @@
1
- const { isString, isFunction } = require('@weave-js/utils')
1
+ const { isString, isFunction } = require('@weave-js/utils');
2
2
 
3
3
  module.exports = (runtime) => {
4
4
  return {
5
5
  localAction: (handler, action) => {
6
- const cacheOptions = runtime.options.cache
6
+ const cacheOptions = runtime.options.cache;
7
7
  const cacheActionOptions = {
8
8
  enabled: !!action.cache
9
- }
9
+ };
10
10
 
11
11
  if (isString(action.cache)) {
12
- cacheActionOptions.keys = action.cache.split(' ')
12
+ cacheActionOptions.keys = action.cache.split(' ');
13
13
  } else if (action.cache && Array.isArray(action.cache.keys)) {
14
- cacheActionOptions.keys = action.cache.keys
14
+ cacheActionOptions.keys = action.cache.keys;
15
15
  }
16
16
 
17
17
  if (cacheActionOptions.enabled) {
18
- const cache = runtime.cache
19
- const isEnabledFunction = isFunction(action.cache.condition)
18
+ const cache = runtime.cache;
19
+ const isEnabledFunction = isFunction(action.cache.condition);
20
20
 
21
21
  return function cacheMiddleware (context, serviceInjections) {
22
22
  // handle enabled function
23
23
  if (isEnabledFunction) {
24
24
  if (!action.cache.enabled.call(null, context)) {
25
25
  // Enabled function returns "false". Cache is disabled.
26
- return handler(context, serviceInjections)
26
+ return handler(context, serviceInjections);
27
27
  }
28
28
  }
29
29
 
@@ -33,74 +33,74 @@ module.exports = (runtime) => {
33
33
  context.data,
34
34
  context.meta,
35
35
  cacheActionOptions.keys
36
- )
36
+ );
37
37
 
38
- context.isCachedResult = false
38
+ context.isCachedResult = false;
39
39
 
40
40
  // Disable caching by meta property.
41
41
  if (context.meta.$noCache === true) {
42
- return handler(context, serviceInjections)
42
+ return handler(context, serviceInjections);
43
43
  }
44
44
 
45
45
  // The cache adapter is not connected yet. In this case, we call the handler regular
46
46
  if (cache.isConnected === false) {
47
- cache.log('Cache adapter is not connected yet. Call handler...')
48
- return handler(context, serviceInjections)
47
+ cache.log('Cache adapter is not connected yet. Call handler...');
48
+ return handler(context, serviceInjections);
49
49
  }
50
50
 
51
51
  if (cacheOptions.lock.enabled) {
52
- let cachePromise
52
+ let cachePromise;
53
53
  if (cacheOptions.lock.staleTime && cache.getWithTTl) {
54
54
 
55
55
  } else {
56
- cachePromise = runtime.cache.get(cacheHashKey)
56
+ cachePromise = runtime.cache.get(cacheHashKey);
57
57
  }
58
58
 
59
59
  return cachePromise.then((cachedResult) => {
60
60
  if (cachedResult !== null) {
61
61
  // Found a cached value. Skip calling handler and return our value
62
- context.isCachedResult = true
63
- return cachedResult
62
+ context.isCachedResult = true;
63
+ return cachedResult;
64
64
  }
65
65
 
66
66
  return cache.lock(cacheHashKey).then((release) => {
67
67
  return cache.get(cacheHashKey).then(cachedResult => {
68
68
  if (cachedResult !== null) {
69
69
  // Found a cached value. Skip calling handler and return our value
70
- context.isCachedResult = true
70
+ context.isCachedResult = true;
71
71
  return release().then(() => {
72
- return cachedResult
73
- })
72
+ return cachedResult;
73
+ });
74
74
  }
75
75
 
76
76
  return handler(context).then((result) => {
77
77
  // Cache the value
78
78
  cache.set(cacheHashKey, result, action.cache.ttl).then(() => {
79
79
  // release the lock
80
- release()
81
- })
82
- return result
83
- })
84
- })
85
- })
86
- })
80
+ release();
81
+ });
82
+ return result;
83
+ });
84
+ });
85
+ });
86
+ });
87
87
  }
88
88
 
89
89
  // Not using cache lock
90
90
  return runtime.cache.get(cacheHashKey).then((cachedResult) => {
91
91
  if (cachedResult !== null) {
92
- context.isCachedResult = true
93
- return cachedResult
92
+ context.isCachedResult = true;
93
+ return cachedResult;
94
94
  }
95
95
 
96
96
  return handler(context, serviceInjections).then((result) => {
97
- runtime.cache.set(cacheHashKey, result, action.cache.ttl)
98
- return result
99
- })
100
- })
101
- }
97
+ runtime.cache.set(cacheHashKey, result, action.cache.ttl);
98
+ return result;
99
+ });
100
+ });
101
+ };
102
102
  }
103
- return handler
103
+ return handler;
104
104
  }
105
- }
106
- }
105
+ };
106
+ };
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Author: Kevin Ries (kevin@fachw3rk.de)
2
+ * Author: Kevin Ries (kevin.ries@fachwerk.io)
3
3
  * -----
4
4
  * Copyright 2021 Fachwerk
5
5
  */
@@ -8,32 +8,32 @@ const {
8
8
  CIRCUIT_HALF_OPENED,
9
9
  CIRCUIT_HALF_OPEN_WAITING,
10
10
  CIRCUIT_OPENED
11
- } = require('../../constants').circuitBreakerStates
11
+ } = require('../../constants').circuitBreakerStates;
12
12
 
13
13
  module.exports = (runtime) => {
14
- const storage = new Map()
15
- let log = null
16
- let circuitBreakerTimer = null
14
+ const storage = new Map();
15
+ let log = null;
16
+ let circuitBreakerTimer = null;
17
17
 
18
18
  function createWindowTimer (windowTime) {
19
- circuitBreakerTimer = setInterval(() => clearEndpointStore(), windowTime)
20
- circuitBreakerTimer.unref()
19
+ circuitBreakerTimer = setInterval(() => clearEndpointStore(), windowTime);
20
+ circuitBreakerTimer.unref();
21
21
  }
22
22
 
23
23
  function clearEndpointStore () {
24
24
  storage.forEach((item) => {
25
25
  if (item.callCounter === 0) {
26
- storage.delete(item.name)
27
- return
26
+ storage.delete(item.name);
27
+ return;
28
28
  }
29
29
 
30
- item.callCounter = 0
31
- item.failureCouter = 0
32
- })
30
+ item.callCounter = 0;
31
+ item.failureCouter = 0;
32
+ });
33
33
  }
34
34
 
35
35
  function getEndpointState (endpoint, options) {
36
- let item = storage.get(endpoint.name)
36
+ let item = storage.get(endpoint.name);
37
37
  if (!item) {
38
38
  item = {
39
39
  endpoint,
@@ -42,127 +42,127 @@ module.exports = (runtime) => {
42
42
  failureCouter: 0,
43
43
  state: CIRCUIT_CLOSED,
44
44
  circuitBreakerTimer: null
45
- }
46
- storage.set(endpoint.name, item)
45
+ };
46
+ storage.set(endpoint.name, item);
47
47
  }
48
48
 
49
- return item
49
+ return item;
50
50
  }
51
51
 
52
52
  function onSuccess (item, options) {
53
- item.callCounter++
53
+ item.callCounter++;
54
54
 
55
55
  if (item.state === CIRCUIT_HALF_OPENED) {
56
- closeCircuitBreaker(item)
56
+ closeCircuitBreaker(item);
57
57
  } else {
58
- checkThreshold(item, options)
58
+ checkThreshold(item, options);
59
59
  }
60
60
  }
61
61
 
62
62
  function onFailure (item, options) {
63
- item.callCounter++
64
- item.failureCouter++
63
+ item.callCounter++;
64
+ item.failureCouter++;
65
65
 
66
- checkThreshold(item, options)
66
+ checkThreshold(item, options);
67
67
  }
68
68
 
69
69
  function checkThreshold (item, options) {
70
70
  if (item.failureCouter >= options.maxFailures) {
71
- openCircuitBreaker(item)
71
+ openCircuitBreaker(item);
72
72
  }
73
73
  }
74
74
 
75
75
  function openCircuitBreaker (item) {
76
- item.state = CIRCUIT_OPENED
77
- item.endpoint.state = false
78
- item.circuitBreakerTimer = setTimeout(() => halfOpenCircuitBreaker(item), item.options.halfOpenTimeout)
79
- item.circuitBreakerTimer.unref()
80
- log.debug(`Circuit breaker has been opened for endpoint '${item.endpoint.name}'`)
76
+ item.state = CIRCUIT_OPENED;
77
+ item.endpoint.state = false;
78
+ item.circuitBreakerTimer = setTimeout(() => halfOpenCircuitBreaker(item), item.options.halfOpenTimeout);
79
+ item.circuitBreakerTimer.unref();
80
+ log.debug(`Circuit breaker has been opened for endpoint '${item.endpoint.name}'`);
81
81
  }
82
82
 
83
83
  function halfOpenCircuitBreaker (item) {
84
- item.state = CIRCUIT_HALF_OPENED
85
- item.endpoint.state = true
84
+ item.state = CIRCUIT_HALF_OPENED;
85
+ item.endpoint.state = true;
86
86
 
87
- log.debug(`Circuit breaker has been half opened for endpoint '${item.endpoint.name}'`)
87
+ log.debug(`Circuit breaker has been half opened for endpoint '${item.endpoint.name}'`);
88
88
 
89
89
  if (item.circuitBreakerTimer) {
90
- clearTimeout(item.circuitBreakerTimer)
91
- item.circuitBreakerTimer = null
90
+ clearTimeout(item.circuitBreakerTimer);
91
+ item.circuitBreakerTimer = null;
92
92
  }
93
93
  }
94
94
 
95
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()
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
100
  }
101
101
 
102
102
  function closeCircuitBreaker (item) {
103
- item.failureCouter = 0
104
- item.callCounter = 0
105
- item.state = CIRCUIT_CLOSED
106
- item.endpoint.state = true
103
+ item.failureCouter = 0;
104
+ item.callCounter = 0;
105
+ item.state = CIRCUIT_CLOSED;
106
+ item.endpoint.state = true;
107
107
 
108
108
  if (item.circuitBreakerTimer) {
109
- clearTimeout(item.circuitBreakerTimer)
110
- item.circuitBreakerTimer = null
109
+ clearTimeout(item.circuitBreakerTimer);
110
+ item.circuitBreakerTimer = null;
111
111
  }
112
112
 
113
- log.debug(`Circuit breaker has been closed for endpoint '${item.endpoint.name}'`)
113
+ log.debug(`Circuit breaker has been closed for endpoint '${item.endpoint.name}'`);
114
114
  }
115
115
 
116
116
  function wrapCircuitBreakerMiddleware (handler, action) {
117
- const options = Object.assign({}, runtime.options.circuitBreaker, action.circuitBreaker || {})
117
+ const options = Object.assign({}, runtime.options.circuitBreaker, action.circuitBreaker || {});
118
118
 
119
119
  if (options.enabled) {
120
120
  return function curcuitBreakerMiddleware (context, serviceInjections) {
121
- const endpoint = context.endpoint
122
- const item = getEndpointState(endpoint, options)
121
+ const endpoint = context.endpoint;
122
+ const item = getEndpointState(endpoint, options);
123
123
 
124
124
  // handle half open states
125
125
  if (item.state === CIRCUIT_HALF_OPENED) {
126
- handleHalfOpen(item, context)
126
+ handleHalfOpen(item, context);
127
127
  }
128
128
 
129
129
  return handler(context, serviceInjections)
130
130
  .then(result => {
131
- const item = getEndpointState(endpoint, options)
132
- onSuccess(item, options)
131
+ const item = getEndpointState(endpoint, options);
132
+ onSuccess(item, options);
133
133
 
134
- return result
134
+ return result;
135
135
  })
136
136
  .catch(error => {
137
137
  if (item && (!error.nodeId || error.nodeId === context.nodeId)) {
138
- onFailure(item, options)
138
+ onFailure(item, options);
139
139
  }
140
140
 
141
- return Promise.reject(error)
142
- })
143
- }
141
+ return Promise.reject(error);
142
+ });
143
+ };
144
144
  }
145
- return handler
145
+ return handler;
146
146
  }
147
147
 
148
148
  return {
149
149
  created () {
150
- log = runtime.createLogger('circuit-breaker')
150
+ log = runtime.createLogger('circuit-breaker');
151
151
 
152
152
  if (runtime.options.metrics.enabled) {
153
153
  // todo: add circuit breaker metrics
154
154
  }
155
155
  },
156
156
  started () {
157
- const { enabled, windowTime } = this.options.circuitBreaker
157
+ const { enabled, windowTime } = this.options.circuitBreaker;
158
158
  if (enabled) {
159
- createWindowTimer(windowTime)
159
+ createWindowTimer(windowTime);
160
160
  }
161
161
  },
162
162
  localAction: wrapCircuitBreakerMiddleware,
163
163
  remoteAction: wrapCircuitBreakerMiddleware,
164
164
  brokerStopped () {
165
- clearInterval(circuitBreakerTimer)
165
+ clearInterval(circuitBreakerTimer);
166
166
  }
167
- }
168
- }
167
+ };
168
+ };