@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.
- package/.eslintrc.js +1 -1
- package/jest.config.js +1 -1
- package/lib/ExtendableError.js +7 -7
- package/lib/broker/context.js +49 -49
- package/lib/broker/defaultOptions.js +8 -9
- package/lib/broker/index.js +160 -164
- package/lib/buildRuntime.js +34 -34
- package/lib/cache/adapters/base.js +50 -74
- package/lib/cache/adapters/inMemory.js +58 -58
- package/lib/cache/adapters/inMemoryLru.js +57 -57
- package/lib/cache/adapters/index.js +3 -39
- package/lib/cache/getCacheKeyByObject.js +31 -0
- package/lib/cache/getPropertyFromDataOrMetadata.js +20 -0
- package/lib/cache/lock.js +30 -24
- package/lib/constants.js +5 -5
- package/lib/errorHandler.js +8 -8
- package/lib/errors.js +35 -35
- package/lib/helper/defineAction.js +2 -2
- package/lib/helper/defineBrokerOptions.js +2 -2
- package/lib/helper/defineService.js +2 -2
- package/lib/index.js +21 -21
- package/lib/logger/base.js +38 -29
- package/lib/logger/format/asHumanReadable.js +15 -15
- package/lib/logger/format/asJson.js +10 -10
- package/lib/logger/format/index.js +3 -3
- package/lib/logger/index.js +24 -24
- package/lib/logger/levels.js +21 -21
- package/lib/logger/tools.js +15 -15
- package/lib/logger/utils/colorize.js +23 -23
- package/lib/logger/utils/format.js +75 -65
- package/lib/metrics/common.js +47 -47
- package/lib/metrics/constants.js +44 -44
- package/lib/metrics/exporter/base.js +8 -8
- package/lib/metrics/exporter/event.js +20 -20
- package/lib/metrics/exporter/index.js +15 -15
- package/lib/metrics/index.js +2 -2
- package/lib/metrics/types/base.js +20 -20
- package/lib/metrics/types/counter.js +6 -6
- package/lib/metrics/types/gauge.js +24 -24
- package/lib/metrics/types/histogram.js +26 -26
- package/lib/metrics/types/index.js +6 -6
- package/lib/metrics/types/info.js +17 -17
- package/lib/middlewares/action-hooks/index.js +38 -38
- package/lib/middlewares/bulkhead/index.js +34 -34
- package/lib/middlewares/cache/index.js +37 -37
- package/lib/middlewares/circuit-breaker/index.js +62 -62
- package/lib/middlewares/context-tracker/index.js +39 -39
- package/lib/middlewares/error-handler/index.js +14 -14
- package/lib/middlewares/index.js +2 -2
- package/lib/middlewares/metrics/getMiddlewareWrapper.js +17 -17
- package/lib/middlewares/metrics/index.js +29 -29
- package/lib/middlewares/retry/index.js +15 -15
- package/lib/middlewares/timeout/index.js +16 -16
- package/lib/middlewares/tracing/index.js +37 -37
- package/lib/middlewares/tracing/tags.js +6 -6
- package/lib/middlewares/validator/index.js +31 -31
- package/lib/registry/actionEndpoint.js +8 -8
- package/lib/registry/collections/actionCollection.js +39 -35
- package/lib/registry/collections/endpointCollection.js +63 -63
- package/lib/registry/collections/eventCollection.js +62 -62
- package/lib/registry/collections/nodeCollection.js +45 -45
- package/lib/registry/collections/serviceCollection.js +61 -55
- package/lib/registry/eventEndpoint.js +14 -14
- package/lib/registry/load-balancer/base.js +3 -3
- package/lib/registry/load-balancer/index.js +7 -7
- package/lib/registry/node.js +27 -27
- package/lib/registry/registry.js +139 -136
- package/lib/registry/service/parseAction.js +16 -16
- package/lib/registry/service/parseEvent.js +18 -18
- package/lib/registry/service/reduceMixins.js +10 -10
- package/lib/registry/service/service.js +72 -72
- package/lib/registry/serviceItem.js +21 -21
- package/lib/runtime/initActionInvoker.js +21 -21
- package/lib/runtime/initCache.js +7 -7
- package/lib/runtime/initContextFactory.js +22 -22
- package/lib/runtime/initEventbus.js +49 -49
- package/lib/runtime/initLogger.js +11 -11
- package/lib/runtime/initMetrics.js +54 -54
- package/lib/runtime/initMiddlewareManager.js +21 -21
- package/lib/runtime/initRegistry.js +6 -6
- package/lib/runtime/initServiceManager.js +85 -68
- package/lib/runtime/initTracing.js +23 -23
- package/lib/runtime/initTransport.js +5 -5
- package/lib/runtime/initUuidFactory.js +4 -4
- package/lib/runtime/initValidator.js +5 -5
- package/lib/tracing/collectors/base.js +22 -22
- package/lib/tracing/collectors/event.js +33 -33
- package/lib/tracing/collectors/index.js +15 -15
- package/lib/tracing/span.js +26 -26
- package/lib/tracing/time.js +8 -8
- package/lib/transport/InboundTransformStream.js +26 -26
- package/lib/transport/adapters/adapteBase.js +30 -30
- package/lib/transport/adapters/adapters.js +4 -4
- package/lib/transport/adapters/dummy/index.js +18 -18
- package/lib/transport/adapters/fromURI.js +13 -13
- package/lib/transport/adapters/getAdapterByName.js +5 -5
- package/lib/transport/adapters/index.js +12 -12
- package/lib/transport/adapters/tcp/discovery/codec.js +4 -4
- package/lib/transport/adapters/tcp/discovery/index.js +62 -62
- package/lib/transport/adapters/tcp/index.js +169 -171
- package/lib/transport/adapters/tcp/tcp-messagetypes.js +7 -7
- package/lib/transport/adapters/tcp/tcpReader.js +39 -39
- package/lib/transport/adapters/tcp/tcpWriteStream.js +26 -26
- package/lib/transport/adapters/tcp/tcpWriter.js +57 -57
- package/lib/transport/adapters/tcp/utils.js +12 -12
- package/lib/transport/createMessage.js +4 -4
- package/lib/transport/createTransport.js +254 -254
- package/lib/transport/errorPayloadFactory.js +14 -17
- package/lib/transport/messageHandlers.js +200 -200
- package/lib/transport/messageTypes.js +19 -19
- package/lib/types.js +28 -15
- package/lib/utils/index.js +1 -1
- package/lib/utils/options.js +44 -44
- package/lib/utils/restoreError.js +4 -4
- package/package.json +4 -4
- package/lib/cache/base.js +0 -136
|
@@ -1,63 +1,34 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Author: Kevin Ries (kevin@
|
|
2
|
+
* Author: Kevin Ries (kevin.ries@fachwerk.io)
|
|
3
3
|
* -----
|
|
4
4
|
* Copyright 2021 Fachwerk
|
|
5
5
|
*/
|
|
6
|
-
const crypto = require('crypto')
|
|
7
|
-
const { isObject,
|
|
8
|
-
const Constants = require('../../metrics/constants')
|
|
9
|
-
const { WeaveError } = require('../../errors')
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* Get property from data or metadata object.
|
|
13
|
-
* @param {any} data data object
|
|
14
|
-
* @param {object} metadata metadata object
|
|
15
|
-
* @param {string} key key
|
|
16
|
-
* @returns {any} Result
|
|
17
|
-
*/
|
|
18
|
-
function getPropertyFromDataOrMetadata (data, metadata, key) {
|
|
19
|
-
// if a key starts with ":", the property is picked from metadata
|
|
20
|
-
if (key.startsWith(':')) {
|
|
21
|
-
// remove ':' from key.
|
|
22
|
-
key = key.replace(':', '')
|
|
23
|
-
return dotGet(metadata, key)
|
|
24
|
-
}
|
|
25
|
-
return dotGet(data, key)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function getCacheKeyByObject (val) {
|
|
29
|
-
if (Array.isArray(val)) {
|
|
30
|
-
return val.map(object => getCacheKeyByObject(object)).join('/')
|
|
31
|
-
} else if (isObject(val)) {
|
|
32
|
-
return Object.keys(val).map(key => {
|
|
33
|
-
return [key, getCacheKeyByObject(val[key])].join('/')
|
|
34
|
-
}).join('/')
|
|
35
|
-
} else if (val !== null) {
|
|
36
|
-
return val.toString()
|
|
37
|
-
} else {
|
|
38
|
-
return 'null'
|
|
39
|
-
}
|
|
40
|
-
}
|
|
6
|
+
const crypto = require('crypto');
|
|
7
|
+
const { isObject, isString } = require('@weave-js/utils');
|
|
8
|
+
const Constants = require('../../metrics/constants');
|
|
9
|
+
const { WeaveError } = require('../../errors');
|
|
10
|
+
const { getCacheKeyByObject } = require('../getCacheKeyByObject');
|
|
11
|
+
const { getPropertyFromDataOrMetadata } = require('../getPropertyFromDataOrMetadata');
|
|
41
12
|
|
|
42
13
|
function generateHash (key) {
|
|
43
14
|
return crypto
|
|
44
15
|
.createHash('sha1')
|
|
45
16
|
.update(key)
|
|
46
|
-
.digest('base64')
|
|
17
|
+
.digest('base64');
|
|
47
18
|
}
|
|
48
19
|
|
|
49
20
|
function registerCacheMetrics (metrics) {
|
|
50
|
-
metrics.register({ type: 'counter', name: Constants.CACHE_GET_TOTAL })
|
|
51
|
-
metrics.register({ type: 'counter', name: Constants.CACHE_SET_TOTAL })
|
|
52
|
-
metrics.register({ type: 'counter', name: Constants.CACHE_FOUND_TOTAL })
|
|
53
|
-
metrics.register({ type: 'counter', name: Constants.CACHE_EXPIRED_TOTAL })
|
|
54
|
-
metrics.register({ type: 'counter', name: Constants.CACHE_DELETED_TOTAL })
|
|
55
|
-
metrics.register({ type: 'counter', name: Constants.CACHE_CLEANED_TOTAL })
|
|
21
|
+
metrics.register({ type: 'counter', name: Constants.CACHE_GET_TOTAL });
|
|
22
|
+
metrics.register({ type: 'counter', name: Constants.CACHE_SET_TOTAL });
|
|
23
|
+
metrics.register({ type: 'counter', name: Constants.CACHE_FOUND_TOTAL });
|
|
24
|
+
metrics.register({ type: 'counter', name: Constants.CACHE_EXPIRED_TOTAL });
|
|
25
|
+
metrics.register({ type: 'counter', name: Constants.CACHE_DELETED_TOTAL });
|
|
26
|
+
metrics.register({ type: 'counter', name: Constants.CACHE_CLEANED_TOTAL });
|
|
56
27
|
}
|
|
57
28
|
|
|
58
29
|
const createCacheBase = (name, runtime, adapterOptions, options) => {
|
|
59
30
|
if (!isString(name)) {
|
|
60
|
-
throw new WeaveError('Name must be a string.')
|
|
31
|
+
throw new WeaveError('Name must be a string.');
|
|
61
32
|
}
|
|
62
33
|
|
|
63
34
|
const cache = {
|
|
@@ -70,74 +41,79 @@ const createCacheBase = (name, runtime, adapterOptions, options) => {
|
|
|
70
41
|
init () {
|
|
71
42
|
// register metrics
|
|
72
43
|
if (runtime.metrics) {
|
|
73
|
-
this.metrics = runtime.metrics
|
|
74
|
-
registerCacheMetrics(runtime.metrics)
|
|
44
|
+
this.metrics = runtime.metrics;
|
|
45
|
+
registerCacheMetrics(runtime.metrics);
|
|
75
46
|
}
|
|
76
47
|
},
|
|
77
48
|
log: runtime.createLogger('CACHER'),
|
|
78
49
|
set (/* hashKey, result, ttl */) {
|
|
79
50
|
/* istanbul ignore next */
|
|
80
|
-
runtime.handleError(new Error('Method not implemented.'))
|
|
51
|
+
runtime.handleError(new Error('Method not implemented.'));
|
|
81
52
|
},
|
|
82
53
|
get (/* hashKey */) {
|
|
83
54
|
/* istanbul ignore next */
|
|
84
|
-
runtime.handleError(new Error('Method not implemented.'))
|
|
55
|
+
runtime.handleError(new Error('Method not implemented.'));
|
|
85
56
|
},
|
|
86
57
|
remove () {
|
|
87
58
|
/* istanbul ignore next */
|
|
88
|
-
runtime.handleError(new Error('Method not implemented.'))
|
|
59
|
+
runtime.handleError(new Error('Method not implemented.'));
|
|
89
60
|
},
|
|
90
61
|
clear () {
|
|
91
62
|
/* istanbul ignore next */
|
|
92
|
-
runtime.handleError(new Error('Method not implemented.'))
|
|
63
|
+
runtime.handleError(new Error('Method not implemented.'));
|
|
93
64
|
},
|
|
94
65
|
stop () {
|
|
95
66
|
/* istanbul ignore next */
|
|
96
|
-
return Promise.resolve()
|
|
67
|
+
return Promise.resolve();
|
|
97
68
|
},
|
|
69
|
+
/**
|
|
70
|
+
* Generates a caching key for action data/metadata.
|
|
71
|
+
* @param {string} actionName Namme of the action
|
|
72
|
+
* @param {any} data Data
|
|
73
|
+
* @param {object=} metadata Metadata
|
|
74
|
+
* @param {Array<string>=} keys Key array
|
|
75
|
+
* @returns {string} Result key string
|
|
76
|
+
*/
|
|
98
77
|
getCachingKey (actionName, data, metadata, keys) {
|
|
99
78
|
if (data || metadata) {
|
|
100
|
-
const prefix = actionName + '
|
|
79
|
+
const prefix = actionName + '.';
|
|
101
80
|
|
|
102
81
|
if (keys) {
|
|
103
82
|
// fast path for single keys
|
|
104
83
|
if (keys.length === 1) {
|
|
105
|
-
const
|
|
106
|
-
const key = getCacheKeyByObject(
|
|
107
|
-
|
|
84
|
+
const cacheKeyData = getPropertyFromDataOrMetadata(data, metadata, keys[0]);
|
|
85
|
+
const key = getCacheKeyByObject(cacheKeyData);
|
|
86
|
+
const value = prefix + (isObject(cacheKeyData) ? key : cacheKeyData);
|
|
87
|
+
return prefix + generateHash(value);
|
|
108
88
|
}
|
|
109
89
|
|
|
110
90
|
// Handle data cache keys
|
|
111
91
|
if (keys.length > 0) {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
} else {
|
|
119
|
-
hash = value
|
|
120
|
-
}
|
|
92
|
+
const valueString = keys.reduce((pre, property, index) => {
|
|
93
|
+
let value = getPropertyFromDataOrMetadata(data, metadata, property);
|
|
94
|
+
value = getCacheKeyByObject(value);
|
|
95
|
+
|
|
96
|
+
return pre + (index > 0 ? '|' : '') + value;
|
|
97
|
+
}, prefix);
|
|
121
98
|
|
|
122
|
-
|
|
123
|
-
}, prefix)
|
|
124
|
-
return res
|
|
99
|
+
return prefix + generateHash(valueString);
|
|
125
100
|
}
|
|
126
101
|
} else {
|
|
127
|
-
|
|
102
|
+
const value = getCacheKeyByObject(data);
|
|
103
|
+
return prefix + generateHash(value);
|
|
128
104
|
}
|
|
129
105
|
}
|
|
130
106
|
|
|
131
|
-
return actionName
|
|
107
|
+
return actionName;
|
|
132
108
|
}
|
|
133
|
-
}
|
|
109
|
+
};
|
|
134
110
|
|
|
135
111
|
Object.defineProperty(cache, 'adapterOptions', {
|
|
136
112
|
value: adapterOptions,
|
|
137
113
|
writable: false
|
|
138
|
-
})
|
|
114
|
+
});
|
|
139
115
|
|
|
140
|
-
return cache
|
|
141
|
-
}
|
|
116
|
+
return cache;
|
|
117
|
+
};
|
|
142
118
|
|
|
143
|
-
module.exports = { createCacheBase }
|
|
119
|
+
module.exports = { createCacheBase };
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Author: Kevin Ries (kevin@
|
|
2
|
+
* Author: Kevin Ries (kevin.ries@fachwerk.io)
|
|
3
3
|
* -----
|
|
4
4
|
* Copyright 2021 Fachwerk
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const { match, defaultsDeep } = require('@weave-js/utils')
|
|
8
|
-
const { createCacheBase } = require('./base')
|
|
9
|
-
const { createLock } = require('../lock')
|
|
10
|
-
const Constants = require('../../metrics/constants')
|
|
7
|
+
const { match, defaultsDeep } = require('@weave-js/utils');
|
|
8
|
+
const { createCacheBase } = require('./base');
|
|
9
|
+
const { createLock } = require('../lock');
|
|
10
|
+
const Constants = require('../../metrics/constants');
|
|
11
11
|
|
|
12
12
|
const defaultAdapterOptions = {
|
|
13
13
|
ttlCheckInterval: 3000
|
|
14
|
-
}
|
|
14
|
+
};
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* @typedef {Object} InMemoryAdapterOptions
|
|
@@ -24,131 +24,131 @@ const defaultAdapterOptions = {
|
|
|
24
24
|
* @returns {any} CacheFactory
|
|
25
25
|
*/
|
|
26
26
|
const createInMemoryCache = (adapterOptions = {}) => (runtime, options = {}) => {
|
|
27
|
-
adapterOptions = defaultsDeep(adapterOptions, defaultAdapterOptions)
|
|
28
|
-
const base = createCacheBase('In-Memory', runtime, adapterOptions, options)
|
|
29
|
-
const storage = new Map()
|
|
27
|
+
adapterOptions = defaultsDeep(adapterOptions, defaultAdapterOptions);
|
|
28
|
+
const base = createCacheBase('In-Memory', runtime, adapterOptions, options);
|
|
29
|
+
const storage = new Map();
|
|
30
30
|
|
|
31
|
-
const lock = createLock()
|
|
31
|
+
const lock = createLock();
|
|
32
32
|
|
|
33
33
|
const ttlTimerHandle = setInterval(() => {
|
|
34
|
-
checkTtl()
|
|
35
|
-
}, adapterOptions.ttlCheckInterval)
|
|
34
|
+
checkTtl();
|
|
35
|
+
}, adapterOptions.ttlCheckInterval);
|
|
36
36
|
|
|
37
|
-
ttlTimerHandle.unref()
|
|
37
|
+
ttlTimerHandle.unref();
|
|
38
38
|
|
|
39
39
|
// if a new broker gets connected, we need to clear the cache
|
|
40
40
|
runtime.bus.on('$transport.connected', () => {
|
|
41
|
-
base.log.debug('Transport adapter connected. Cache will be cleared.')
|
|
42
|
-
cache.clear()
|
|
43
|
-
})
|
|
41
|
+
base.log.debug('Transport adapter connected. Cache will be cleared.');
|
|
42
|
+
cache.clear();
|
|
43
|
+
});
|
|
44
44
|
|
|
45
45
|
const checkTtl = () => {
|
|
46
|
-
const now = Date.now()
|
|
46
|
+
const now = Date.now();
|
|
47
47
|
|
|
48
48
|
storage.forEach((item, hashKey) => {
|
|
49
49
|
if (item.expire && item.expire < now) {
|
|
50
|
-
cache.log.debug(`Delete ${hashKey}`)
|
|
51
|
-
storage.delete(hashKey)
|
|
50
|
+
cache.log.debug(`Delete ${hashKey}`);
|
|
51
|
+
storage.delete(hashKey);
|
|
52
52
|
}
|
|
53
|
-
})
|
|
54
|
-
}
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
55
|
|
|
56
56
|
const cache = Object.assign(
|
|
57
57
|
{},
|
|
58
58
|
base,
|
|
59
59
|
{
|
|
60
60
|
init () {
|
|
61
|
-
base.init()
|
|
62
|
-
cache.isConnected = true
|
|
61
|
+
base.init();
|
|
62
|
+
cache.isConnected = true;
|
|
63
63
|
},
|
|
64
64
|
get (cacheKey) {
|
|
65
|
-
base.log.debug(`Get ${cacheKey}`)
|
|
65
|
+
base.log.debug(`Get ${cacheKey}`);
|
|
66
66
|
|
|
67
67
|
if (base.metrics) {
|
|
68
|
-
base.metrics.increment(Constants.CACHE_GET_TOTAL)
|
|
68
|
+
base.metrics.increment(Constants.CACHE_GET_TOTAL);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
const item = storage.get(cacheKey)
|
|
71
|
+
const item = storage.get(cacheKey);
|
|
72
72
|
|
|
73
73
|
if (item) {
|
|
74
|
-
cache.log.debug(`Found ${cacheKey}`)
|
|
74
|
+
cache.log.debug(`Found ${cacheKey}`);
|
|
75
75
|
|
|
76
76
|
if (base.metrics) {
|
|
77
|
-
base.metrics.increment(Constants.CACHE_FOUND_TOTAL)
|
|
77
|
+
base.metrics.increment(Constants.CACHE_FOUND_TOTAL);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
if (item.expire && item.expire < Date.now()) {
|
|
81
|
-
cache.log.debug(`Delete ${cacheKey}`)
|
|
82
|
-
storage.delete(cacheKey)
|
|
81
|
+
cache.log.debug(`Delete ${cacheKey}`);
|
|
82
|
+
storage.delete(cacheKey);
|
|
83
83
|
if (base.metrics) {
|
|
84
|
-
base.metrics.increment(Constants.CACHE_EXPIRED_TOTAL)
|
|
84
|
+
base.metrics.increment(Constants.CACHE_EXPIRED_TOTAL);
|
|
85
85
|
}
|
|
86
|
-
return Promise.resolve(null)
|
|
86
|
+
return Promise.resolve(null);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
return Promise.resolve(item.data)
|
|
89
|
+
return Promise.resolve(item.data);
|
|
90
90
|
}
|
|
91
|
-
return Promise.resolve(null)
|
|
91
|
+
return Promise.resolve(null);
|
|
92
92
|
},
|
|
93
93
|
set (hashKey, data, ttl) {
|
|
94
94
|
if (base.metrics) {
|
|
95
|
-
base.metrics.increment(Constants.CACHE_SET_TOTAL)
|
|
95
|
+
base.metrics.increment(Constants.CACHE_SET_TOTAL);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
// if ttl is not set in action cache settings, use options ttl
|
|
99
99
|
if (ttl == null) {
|
|
100
|
-
ttl = options.ttl
|
|
100
|
+
ttl = options.ttl;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
storage.set(hashKey, {
|
|
104
104
|
data,
|
|
105
105
|
expire: ttl ? Date.now() + ttl : null
|
|
106
|
-
})
|
|
106
|
+
});
|
|
107
107
|
|
|
108
|
-
base.log.debug(`Set ${hashKey}`)
|
|
108
|
+
base.log.debug(`Set ${hashKey}`);
|
|
109
109
|
|
|
110
|
-
return Promise.resolve(data)
|
|
110
|
+
return Promise.resolve(data);
|
|
111
111
|
},
|
|
112
112
|
remove (hashKey) {
|
|
113
113
|
if (base.metrics) {
|
|
114
|
-
base.metrics.increment(Constants.CACHE_DELETED_TOTAL)
|
|
114
|
+
base.metrics.increment(Constants.CACHE_DELETED_TOTAL);
|
|
115
115
|
}
|
|
116
|
-
storage.delete(hashKey)
|
|
117
|
-
base.log.debug(`Delete ${hashKey}`)
|
|
116
|
+
storage.delete(hashKey);
|
|
117
|
+
base.log.debug(`Delete cached object with key ${hashKey}`);
|
|
118
118
|
|
|
119
|
-
return Promise.resolve()
|
|
119
|
+
return Promise.resolve();
|
|
120
120
|
},
|
|
121
121
|
clear (pattern = '**') {
|
|
122
122
|
if (base.metrics) {
|
|
123
|
-
base.metrics.increment(Constants.CACHE_DELETED_TOTAL)
|
|
123
|
+
base.metrics.increment(Constants.CACHE_DELETED_TOTAL);
|
|
124
124
|
}
|
|
125
|
+
|
|
125
126
|
storage.forEach((_, key) => {
|
|
126
127
|
if (match(key, pattern)) {
|
|
127
|
-
|
|
128
|
-
this.remove(key)
|
|
128
|
+
this.remove(key);
|
|
129
129
|
}
|
|
130
|
-
})
|
|
131
|
-
return Promise.resolve()
|
|
130
|
+
});
|
|
131
|
+
return Promise.resolve();
|
|
132
132
|
},
|
|
133
133
|
lock (key, ttl) {
|
|
134
134
|
return lock.acquire(key, ttl).then(() => {
|
|
135
|
-
return () => lock.release(key)
|
|
136
|
-
})
|
|
135
|
+
return () => lock.release(key);
|
|
136
|
+
});
|
|
137
137
|
},
|
|
138
138
|
tryAcquireLock (key, ttl) {
|
|
139
139
|
if (lock.isLocked(key)) {
|
|
140
|
-
return Promise.reject(new Error('Locked'))
|
|
140
|
+
return Promise.reject(new Error('Locked'));
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
return lock.acquire(key, ttl).then(() => {
|
|
144
|
-
return () => lock.release(key)
|
|
145
|
-
})
|
|
144
|
+
return () => lock.release(key);
|
|
145
|
+
});
|
|
146
146
|
},
|
|
147
147
|
async stop () {
|
|
148
|
-
clearInterval(ttlTimerHandle)
|
|
148
|
+
clearInterval(ttlTimerHandle);
|
|
149
149
|
}
|
|
150
|
-
})
|
|
151
|
-
return cache
|
|
152
|
-
}
|
|
150
|
+
});
|
|
151
|
+
return cache;
|
|
152
|
+
};
|
|
153
153
|
|
|
154
|
-
module.exports = { createInMemoryCache }
|
|
154
|
+
module.exports = { createInMemoryCache };
|
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Author: Kevin Ries (kevin@
|
|
2
|
+
* Author: Kevin Ries (kevin.ries@fachwerk.io)
|
|
3
3
|
* -----
|
|
4
4
|
* Copyright 2021 Fachwerk
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const { match } = require('@weave-js/utils')
|
|
8
|
-
const { createCacheBase } = require('./base')
|
|
9
|
-
const { createLock } = require('../lock')
|
|
10
|
-
const Constants = require('../../metrics/constants')
|
|
7
|
+
const { match } = require('@weave-js/utils');
|
|
8
|
+
const { createCacheBase } = require('./base');
|
|
9
|
+
const { createLock } = require('../lock');
|
|
10
|
+
const Constants = require('../../metrics/constants');
|
|
11
11
|
|
|
12
12
|
const createInMemoryLruCache = (adapterOptions) => (runtime, options = {}) => {
|
|
13
|
-
const name = 'In-Memory'
|
|
14
|
-
const base = createCacheBase(name, runtime, options)
|
|
15
|
-
const storage = new Map()
|
|
13
|
+
const name = 'In-Memory';
|
|
14
|
+
const base = createCacheBase(name, runtime, options);
|
|
15
|
+
const storage = new Map();
|
|
16
16
|
|
|
17
|
-
const lock = createLock()
|
|
17
|
+
const lock = createLock();
|
|
18
18
|
|
|
19
19
|
const timer = setInterval(() => {
|
|
20
|
-
checkTtl()
|
|
21
|
-
}, 3000)
|
|
20
|
+
checkTtl();
|
|
21
|
+
}, 3000);
|
|
22
22
|
|
|
23
|
-
timer.unref()
|
|
23
|
+
timer.unref();
|
|
24
24
|
|
|
25
25
|
// if a new broker gets connected, we need to clear the cache
|
|
26
26
|
runtime.bus.on('$transport.connected', () => {
|
|
27
|
-
base.log.debug('Transport adapter connected. Cache will be cleared.')
|
|
28
|
-
cache.clear()
|
|
29
|
-
})
|
|
27
|
+
base.log.debug('Transport adapter connected. Cache will be cleared.');
|
|
28
|
+
cache.clear();
|
|
29
|
+
});
|
|
30
30
|
|
|
31
31
|
const checkTtl = () => {
|
|
32
|
-
const now = Date.now()
|
|
32
|
+
const now = Date.now();
|
|
33
33
|
|
|
34
34
|
storage.forEach((item, hashKey) => {
|
|
35
35
|
if (item.expire && item.expire < now) {
|
|
36
|
-
cache.log.debug(`Delete ${hashKey}`)
|
|
37
|
-
storage.delete(hashKey)
|
|
36
|
+
cache.log.debug(`Delete ${hashKey}`);
|
|
37
|
+
storage.delete(hashKey);
|
|
38
38
|
}
|
|
39
|
-
})
|
|
40
|
-
}
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
41
|
|
|
42
42
|
const cache = Object.assign(
|
|
43
43
|
{},
|
|
@@ -45,96 +45,96 @@ const createInMemoryLruCache = (adapterOptions) => (runtime, options = {}) => {
|
|
|
45
45
|
{
|
|
46
46
|
name,
|
|
47
47
|
init () {
|
|
48
|
-
base.init()
|
|
49
|
-
cache.isConnected = true
|
|
48
|
+
base.init();
|
|
49
|
+
cache.isConnected = true;
|
|
50
50
|
},
|
|
51
51
|
get (cacheKey) {
|
|
52
|
-
base.log.debug(`Get ${cacheKey}`)
|
|
52
|
+
base.log.debug(`Get ${cacheKey}`);
|
|
53
53
|
|
|
54
54
|
if (base.metrics) {
|
|
55
|
-
base.metrics.increment(Constants.CACHE_GET_TOTAL)
|
|
55
|
+
base.metrics.increment(Constants.CACHE_GET_TOTAL);
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
const item = storage.get(cacheKey)
|
|
58
|
+
const item = storage.get(cacheKey);
|
|
59
59
|
|
|
60
60
|
if (item) {
|
|
61
|
-
cache.log.debug(`Found ${cacheKey}`)
|
|
61
|
+
cache.log.debug(`Found ${cacheKey}`);
|
|
62
62
|
|
|
63
63
|
if (base.metrics) {
|
|
64
|
-
base.metrics.increment(Constants.CACHE_FOUND_TOTAL)
|
|
64
|
+
base.metrics.increment(Constants.CACHE_FOUND_TOTAL);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
if (item.expire && item.expire < Date.now()) {
|
|
68
|
-
cache.log.debug(`Delete ${cacheKey}`)
|
|
69
|
-
storage.delete(cacheKey)
|
|
68
|
+
cache.log.debug(`Delete ${cacheKey}`);
|
|
69
|
+
storage.delete(cacheKey);
|
|
70
70
|
if (base.metrics) {
|
|
71
|
-
base.metrics.increment(Constants.CACHE_EXPIRED_TOTAL)
|
|
71
|
+
base.metrics.increment(Constants.CACHE_EXPIRED_TOTAL);
|
|
72
72
|
}
|
|
73
|
-
return Promise.resolve(null)
|
|
73
|
+
return Promise.resolve(null);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
return Promise.resolve(item.data)
|
|
76
|
+
return Promise.resolve(item.data);
|
|
77
77
|
}
|
|
78
|
-
return Promise.resolve(null)
|
|
78
|
+
return Promise.resolve(null);
|
|
79
79
|
},
|
|
80
80
|
set (hashKey, data, ttl) {
|
|
81
81
|
if (base.metrics) {
|
|
82
|
-
base.metrics.increment(Constants.CACHE_SET_TOTAL)
|
|
82
|
+
base.metrics.increment(Constants.CACHE_SET_TOTAL);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
if (ttl == null) {
|
|
86
|
-
ttl = options.ttl
|
|
86
|
+
ttl = options.ttl;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
storage.set(hashKey, {
|
|
90
90
|
data,
|
|
91
91
|
expire: ttl ? Date.now() + ttl : null
|
|
92
|
-
})
|
|
92
|
+
});
|
|
93
93
|
|
|
94
|
-
base.log.debug(`Set ${hashKey}`)
|
|
94
|
+
base.log.debug(`Set ${hashKey}`);
|
|
95
95
|
|
|
96
|
-
return Promise.resolve(data)
|
|
96
|
+
return Promise.resolve(data);
|
|
97
97
|
},
|
|
98
98
|
remove (hashKey) {
|
|
99
99
|
if (base.metrics) {
|
|
100
|
-
base.metrics.increment(Constants.CACHE_DELETED_TOTAL)
|
|
100
|
+
base.metrics.increment(Constants.CACHE_DELETED_TOTAL);
|
|
101
101
|
}
|
|
102
|
-
storage.delete(hashKey)
|
|
103
|
-
base.log.debug(`Delete ${hashKey}`)
|
|
102
|
+
storage.delete(hashKey);
|
|
103
|
+
base.log.debug(`Delete ${hashKey}`);
|
|
104
104
|
|
|
105
|
-
return Promise.resolve()
|
|
105
|
+
return Promise.resolve();
|
|
106
106
|
},
|
|
107
107
|
clear (pattern = '**') {
|
|
108
108
|
if (base.metrics) {
|
|
109
|
-
base.metrics.increment(Constants.CACHE_DELETED_TOTAL)
|
|
109
|
+
base.metrics.increment(Constants.CACHE_DELETED_TOTAL);
|
|
110
110
|
}
|
|
111
111
|
storage.forEach((_, key) => {
|
|
112
112
|
if (match(key, pattern)) {
|
|
113
|
-
base.log.debug(`Delete ${key}`)
|
|
114
|
-
this.remove(key)
|
|
113
|
+
base.log.debug(`Delete ${key}`);
|
|
114
|
+
this.remove(key);
|
|
115
115
|
}
|
|
116
|
-
})
|
|
117
|
-
return Promise.resolve()
|
|
116
|
+
});
|
|
117
|
+
return Promise.resolve();
|
|
118
118
|
},
|
|
119
119
|
lock (key, ttl) {
|
|
120
120
|
return lock.acquire(key, ttl).then(() => {
|
|
121
|
-
return () => lock.release(key)
|
|
122
|
-
})
|
|
121
|
+
return () => lock.release(key);
|
|
122
|
+
});
|
|
123
123
|
},
|
|
124
124
|
tryAcquireLock (key, ttl) {
|
|
125
125
|
if (lock.isLocked(key)) {
|
|
126
|
-
return Promise.reject(new Error('Locked'))
|
|
126
|
+
return Promise.reject(new Error('Locked'));
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
return lock.acquire(key, ttl).then(() => {
|
|
130
|
-
return () => lock.release(key)
|
|
131
|
-
})
|
|
130
|
+
return () => lock.release(key);
|
|
131
|
+
});
|
|
132
132
|
},
|
|
133
133
|
stop () {
|
|
134
|
-
clearInterval(timer)
|
|
134
|
+
clearInterval(timer);
|
|
135
135
|
}
|
|
136
|
-
})
|
|
137
|
-
return cache
|
|
138
|
-
}
|
|
136
|
+
});
|
|
137
|
+
return cache;
|
|
138
|
+
};
|
|
139
139
|
|
|
140
|
-
module.exports = { createInMemoryLruCache }
|
|
140
|
+
module.exports = { createInMemoryLruCache };
|
|
@@ -1,46 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Author: Kevin Ries (kevin@
|
|
2
|
+
* Author: Kevin Ries (kevin.ries@fachwerk.io)
|
|
3
3
|
* -----
|
|
4
4
|
* Copyright 2021 Fachwerk
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
...require('./base'),
|
|
9
|
-
...require('./inMemory')
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
// exports.resolve = (cacheOptions) => {
|
|
14
|
-
// const getByName = name => {
|
|
15
|
-
// if (!name) {
|
|
16
|
-
// return null
|
|
17
|
-
// }
|
|
18
|
-
|
|
19
|
-
// const n = Object
|
|
20
|
-
// .keys(adapters)
|
|
21
|
-
// .find(n => n.toLowerCase() === name.toLowerCase())
|
|
22
|
-
|
|
23
|
-
// if (n) {
|
|
24
|
-
// return adapters[n]
|
|
25
|
-
// }
|
|
26
|
-
// }
|
|
27
|
-
|
|
28
|
-
// let cacheFactory
|
|
29
|
-
|
|
30
|
-
// if (cacheOptions === true) {
|
|
31
|
-
// cacheFactory = this.adapters.Memory
|
|
32
|
-
// } else if (isString(cacheOptions)) {
|
|
33
|
-
// const cache = getByName(cacheOptions)
|
|
34
|
-
|
|
35
|
-
// if (cache) {
|
|
36
|
-
// cacheFactory = cache()
|
|
37
|
-
// } else {
|
|
38
|
-
// throw new WeaveBrokerOptionsError(`Unknown cache type "${cacheOptions}"`)
|
|
39
|
-
// }
|
|
40
|
-
// } else if (isFunction(cacheOptions)) {
|
|
41
|
-
// cacheFactory = cacheOptions
|
|
42
|
-
// }
|
|
43
|
-
// if (cacheFactory) {
|
|
44
|
-
// return cacheFactory
|
|
45
|
-
// }
|
|
46
|
-
// }
|
|
9
|
+
...require('./inMemory')
|
|
10
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const { isObject, isString } = require('@weave-js/utils');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Get property from data or metadata object.
|
|
5
|
+
* @param {any} value Value
|
|
6
|
+
* @returns {string} Cache key
|
|
7
|
+
*/
|
|
8
|
+
const getCacheKeyByObject = (value) => {
|
|
9
|
+
if (Array.isArray(value)) {
|
|
10
|
+
return '[' + value.map(object => getCacheKeyByObject(object)).join(',') + ']';
|
|
11
|
+
} else if (isObject(value)) {
|
|
12
|
+
// Handle date objects
|
|
13
|
+
if (value instanceof Date) {
|
|
14
|
+
return value.toISOString();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return '{' + Object.keys(value)
|
|
18
|
+
.map((key) => {
|
|
19
|
+
return [key, getCacheKeyByObject(value[key])].join(':');
|
|
20
|
+
})
|
|
21
|
+
.join(',') + '}';
|
|
22
|
+
} else if (isString(value)) {
|
|
23
|
+
return value;
|
|
24
|
+
} else if (typeof value === 'boolean' || typeof value === 'number') {
|
|
25
|
+
return value.toString();
|
|
26
|
+
} else {
|
|
27
|
+
return 'null';
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
module.exports = { getCacheKeyByObject };
|