@weave-js/core 0.11.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,6 +10,7 @@
10
10
 
11
11
  /** @module weave */
12
12
  const os = require('os')
13
+ const { createInMemoryCache } = require('../cache/adapters/inMemory.js')
13
14
  const { loadBalancingStrategy } = require('../constants')
14
15
 
15
16
  /**
@@ -28,7 +29,7 @@ exports.getDefaultOptions = () => {
28
29
  },
29
30
  cache: {
30
31
  enabled: false,
31
- adapter: 'memory',
32
+ adapter: createInMemoryCache(),
32
33
  ttl: 3000,
33
34
  lock: {
34
35
  enabled: false
@@ -257,7 +257,7 @@ exports.createBrokerInstance = (runtime) => {
257
257
  // handle arrays
258
258
  const pongs = {}
259
259
 
260
- const nodes = registry.getNodeList({})
260
+ const nodes = registry.nodeCollection.list({})
261
261
  .filter(node => !node.isLocal)
262
262
  .map(node => node.id)
263
263
 
@@ -0,0 +1,143 @@
1
+ /*
2
+ * Author: Kevin Ries (kevin@fachw3rk.de)
3
+ * -----
4
+ * Copyright 2021 Fachwerk
5
+ */
6
+ const crypto = require('crypto')
7
+ const { isObject, dotGet, isString } = require('@weave-js/utils')
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
+ }
41
+
42
+ function generateHash (key) {
43
+ return crypto
44
+ .createHash('sha1')
45
+ .update(key)
46
+ .digest('base64')
47
+ }
48
+
49
+ 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 })
56
+ }
57
+
58
+ const createCacheBase = (name, runtime, adapterOptions, options) => {
59
+ if (!isString(name)) {
60
+ throw new WeaveError('Name must be a string.')
61
+ }
62
+
63
+ const cache = {
64
+ name,
65
+ isConnected: false,
66
+ runtime,
67
+ options: Object.assign({
68
+ ttl: null
69
+ }, options),
70
+ init () {
71
+ // register metrics
72
+ if (runtime.metrics) {
73
+ this.metrics = runtime.metrics
74
+ registerCacheMetrics(runtime.metrics)
75
+ }
76
+ },
77
+ log: runtime.createLogger('CACHER'),
78
+ set (/* hashKey, result, ttl */) {
79
+ /* istanbul ignore next */
80
+ runtime.handleError(new Error('Method not implemented.'))
81
+ },
82
+ get (/* hashKey */) {
83
+ /* istanbul ignore next */
84
+ runtime.handleError(new Error('Method not implemented.'))
85
+ },
86
+ remove () {
87
+ /* istanbul ignore next */
88
+ runtime.handleError(new Error('Method not implemented.'))
89
+ },
90
+ clear () {
91
+ /* istanbul ignore next */
92
+ runtime.handleError(new Error('Method not implemented.'))
93
+ },
94
+ stop () {
95
+ /* istanbul ignore next */
96
+ return Promise.resolve()
97
+ },
98
+ getCachingKey (actionName, data, metadata, keys) {
99
+ if (data || metadata) {
100
+ const prefix = actionName + ':'
101
+
102
+ if (keys) {
103
+ // fast path for single keys
104
+ if (keys.length === 1) {
105
+ const value = getPropertyFromDataOrMetadata(data, metadata, keys[0])
106
+ const key = getCacheKeyByObject(value)
107
+ return prefix + (isObject(value) ? key : value)
108
+ }
109
+
110
+ // Handle data cache keys
111
+ if (keys.length > 0) {
112
+ const res = keys.reduce((pre, property, index) => {
113
+ const value = getPropertyFromDataOrMetadata(data, metadata, property)
114
+ let hash
115
+ if (isObject(value)) {
116
+ const key = getCacheKeyByObject(value)
117
+ hash = generateHash(key)
118
+ } else {
119
+ hash = value
120
+ }
121
+
122
+ return pre + (index > 0 ? '|' : '') + hash
123
+ }, prefix)
124
+ return res
125
+ }
126
+ } else {
127
+ return prefix + generateHash(getCacheKeyByObject(data))
128
+ }
129
+ }
130
+
131
+ return actionName
132
+ }
133
+ }
134
+
135
+ Object.defineProperty(cache, 'adapterOptions', {
136
+ value: adapterOptions,
137
+ writable: false
138
+ })
139
+
140
+ return cache
141
+ }
142
+
143
+ module.exports = { createCacheBase }
@@ -0,0 +1,154 @@
1
+ /*
2
+ * Author: Kevin Ries (kevin@fachw3rk.de)
3
+ * -----
4
+ * Copyright 2021 Fachwerk
5
+ */
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')
11
+
12
+ const defaultAdapterOptions = {
13
+ ttlCheckInterval: 3000
14
+ }
15
+
16
+ /**
17
+ * @typedef {Object} InMemoryAdapterOptions
18
+ * @property {number=} ttlCheckInterval TTL check interval
19
+ */
20
+
21
+ /**
22
+ * Create an in-memory cache adapter.
23
+ * @param {InMemoryAdapterOptions} adapterOptions Adapter options
24
+ * @returns {any} CacheFactory
25
+ */
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()
30
+
31
+ const lock = createLock()
32
+
33
+ const ttlTimerHandle = setInterval(() => {
34
+ checkTtl()
35
+ }, adapterOptions.ttlCheckInterval)
36
+
37
+ ttlTimerHandle.unref()
38
+
39
+ // if a new broker gets connected, we need to clear the cache
40
+ runtime.bus.on('$transport.connected', () => {
41
+ base.log.debug('Transport adapter connected. Cache will be cleared.')
42
+ cache.clear()
43
+ })
44
+
45
+ const checkTtl = () => {
46
+ const now = Date.now()
47
+
48
+ storage.forEach((item, hashKey) => {
49
+ if (item.expire && item.expire < now) {
50
+ cache.log.debug(`Delete ${hashKey}`)
51
+ storage.delete(hashKey)
52
+ }
53
+ })
54
+ }
55
+
56
+ const cache = Object.assign(
57
+ {},
58
+ base,
59
+ {
60
+ init () {
61
+ base.init()
62
+ cache.isConnected = true
63
+ },
64
+ get (cacheKey) {
65
+ base.log.debug(`Get ${cacheKey}`)
66
+
67
+ if (base.metrics) {
68
+ base.metrics.increment(Constants.CACHE_GET_TOTAL)
69
+ }
70
+
71
+ const item = storage.get(cacheKey)
72
+
73
+ if (item) {
74
+ cache.log.debug(`Found ${cacheKey}`)
75
+
76
+ if (base.metrics) {
77
+ base.metrics.increment(Constants.CACHE_FOUND_TOTAL)
78
+ }
79
+
80
+ if (item.expire && item.expire < Date.now()) {
81
+ cache.log.debug(`Delete ${cacheKey}`)
82
+ storage.delete(cacheKey)
83
+ if (base.metrics) {
84
+ base.metrics.increment(Constants.CACHE_EXPIRED_TOTAL)
85
+ }
86
+ return Promise.resolve(null)
87
+ }
88
+
89
+ return Promise.resolve(item.data)
90
+ }
91
+ return Promise.resolve(null)
92
+ },
93
+ set (hashKey, data, ttl) {
94
+ if (base.metrics) {
95
+ base.metrics.increment(Constants.CACHE_SET_TOTAL)
96
+ }
97
+
98
+ // if ttl is not set in action cache settings, use options ttl
99
+ if (ttl == null) {
100
+ ttl = options.ttl
101
+ }
102
+
103
+ storage.set(hashKey, {
104
+ data,
105
+ expire: ttl ? Date.now() + ttl : null
106
+ })
107
+
108
+ base.log.debug(`Set ${hashKey}`)
109
+
110
+ return Promise.resolve(data)
111
+ },
112
+ remove (hashKey) {
113
+ if (base.metrics) {
114
+ base.metrics.increment(Constants.CACHE_DELETED_TOTAL)
115
+ }
116
+ storage.delete(hashKey)
117
+ base.log.debug(`Delete ${hashKey}`)
118
+
119
+ return Promise.resolve()
120
+ },
121
+ clear (pattern = '**') {
122
+ if (base.metrics) {
123
+ base.metrics.increment(Constants.CACHE_DELETED_TOTAL)
124
+ }
125
+ storage.forEach((_, key) => {
126
+ if (match(key, pattern)) {
127
+ base.log.debug(`Delete ${key}`)
128
+ this.remove(key)
129
+ }
130
+ })
131
+ return Promise.resolve()
132
+ },
133
+ lock (key, ttl) {
134
+ return lock.acquire(key, ttl).then(() => {
135
+ return () => lock.release(key)
136
+ })
137
+ },
138
+ tryAcquireLock (key, ttl) {
139
+ if (lock.isLocked(key)) {
140
+ return Promise.reject(new Error('Locked'))
141
+ }
142
+
143
+ return lock.acquire(key, ttl).then(() => {
144
+ return () => lock.release(key)
145
+ })
146
+ },
147
+ async stop () {
148
+ clearInterval(ttlTimerHandle)
149
+ }
150
+ })
151
+ return cache
152
+ }
153
+
154
+ module.exports = { createInMemoryCache }
@@ -6,13 +6,13 @@
6
6
 
7
7
  const { match } = require('@weave-js/utils')
8
8
  const { createCacheBase } = require('./base')
9
- const { createLock } = require('./lock')
10
- const Constants = require('../metrics/constants')
9
+ const { createLock } = require('../lock')
10
+ const Constants = require('../../metrics/constants')
11
11
 
12
- const makeInMemoryCache = (runtime, options = {}) => {
13
- const base = createCacheBase(runtime, options)
12
+ const createInMemoryLruCache = (adapterOptions) => (runtime, options = {}) => {
13
+ const name = 'In-Memory'
14
+ const base = createCacheBase(name, runtime, options)
14
15
  const storage = new Map()
15
- const name = 'Memory'
16
16
 
17
17
  const lock = createLock()
18
18
 
@@ -121,7 +121,7 @@ const makeInMemoryCache = (runtime, options = {}) => {
121
121
  return () => lock.release(key)
122
122
  })
123
123
  },
124
- tryLock (key, ttl) {
124
+ tryAcquireLock (key, ttl) {
125
125
  if (lock.isLocked(key)) {
126
126
  return Promise.reject(new Error('Locked'))
127
127
  }
@@ -137,4 +137,4 @@ const makeInMemoryCache = (runtime, options = {}) => {
137
137
  return cache
138
138
  }
139
139
 
140
- module.exports = makeInMemoryCache
140
+ module.exports = { createInMemoryLruCache }
@@ -0,0 +1,46 @@
1
+ /*
2
+ * Author: Kevin Ries (kevin@fachw3rk.de)
3
+ * -----
4
+ * Copyright 2021 Fachwerk
5
+ */
6
+
7
+ module.exports = {
8
+ ...require('./base'),
9
+ ...require('./inMemory'),
10
+ ...require('./inMemoryLru')
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
+ // }
package/lib/cache/base.js CHANGED
@@ -4,8 +4,26 @@
4
4
  * Copyright 2021 Fachwerk
5
5
  */
6
6
  const crypto = require('crypto')
7
- const { isObject } = require('@weave-js/utils')
7
+ const { isObject, dotGet, isString } = require('@weave-js/utils')
8
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
+ }
9
27
 
10
28
  function getCacheKeyByObject (val) {
11
29
  if (Array.isArray(val)) {
@@ -37,8 +55,13 @@ function registerCacheMetrics (metrics) {
37
55
  metrics.register({ type: 'counter', name: Constants.CACHE_CLEANED_TOTAL })
38
56
  }
39
57
 
40
- exports.createCacheBase = (runtime, options) => {
58
+ exports.createCacheBase = (name, runtime, options) => {
59
+ if (!isString(name)) {
60
+ throw new WeaveError('Name needs to be a string.')
61
+ }
62
+
41
63
  const cache = {
64
+ name,
42
65
  isConnected: false,
43
66
  runtime,
44
67
  options: Object.assign({
@@ -72,20 +95,22 @@ exports.createCacheBase = (runtime, options) => {
72
95
  /* istanbul ignore next */
73
96
  return Promise.resolve()
74
97
  },
75
- getCachingHash (actionName, params, meta, keys) {
76
- if (params || meta) {
77
- const prefix = `${actionName}:`
98
+ getCachingKey (actionName, data, metadata, keys) {
99
+ if (data || metadata) {
100
+ const prefix = actionName + ':'
78
101
 
79
102
  if (keys) {
103
+ // fast path for single keys
80
104
  if (keys.length === 1) {
81
- const value = params[keys[0]]
105
+ const value = getPropertyFromDataOrMetadata(data, metadata, keys[0])
82
106
  const key = getCacheKeyByObject(value)
83
107
  return prefix + (isObject(value) ? key : value)
84
108
  }
85
109
 
110
+ // Handle data cache keys
86
111
  if (keys.length > 0) {
87
- const res = keys.reduce((pre, property, i) => {
88
- const value = params[property]
112
+ const res = keys.reduce((pre, property, index) => {
113
+ const value = getPropertyFromDataOrMetadata(data, metadata, property)
89
114
  let hash
90
115
  if (isObject(value)) {
91
116
  const key = getCacheKeyByObject(value)
@@ -94,12 +119,12 @@ exports.createCacheBase = (runtime, options) => {
94
119
  hash = value
95
120
  }
96
121
 
97
- return pre + (i > 0 ? '|' : '') + hash
122
+ return pre + (index > 0 ? '|' : '') + hash
98
123
  }, prefix)
99
124
  return res
100
125
  }
101
126
  } else {
102
- return prefix + generateHash(getCacheKeyByObject(params))
127
+ return prefix + generateHash(getCacheKeyByObject(data))
103
128
  }
104
129
  }
105
130
 
@@ -107,41 +132,5 @@ exports.createCacheBase = (runtime, options) => {
107
132
  }
108
133
  }
109
134
 
110
- // cache.middleware = (runtime) => {
111
- // return {
112
- // localAction: (handler, action) => {
113
- // const cacheOptions = Object.assign({ enabled: true }, isObject(action.cache) ? action.cache : { enabled: !!action.cache })
114
- // if (cacheOptions.enabled) {
115
- // return function cacheMiddleware (context, serviceInjections) {
116
- // const cacheHashKey = runtime.cache.getCachingHash(action.name, context.data, context.meta, action.cache.keys)
117
- // context.isCachedResult = false
118
-
119
- // if (context.meta.$noCache === true) {
120
- // return handler(context, serviceInjections)
121
- // }
122
-
123
- // if (runtime.cache.isConnected === false) {
124
- // runtime.cache.log('Cache adapter is not connected yet. Call handler...')
125
- // return handler(context, serviceInjections)
126
- // }
127
-
128
- // return runtime.cache.get(cacheHashKey).then((cachedResult) => {
129
- // if (cachedResult !== null) {
130
- // context.isCachedResult = true
131
- // return cachedResult
132
- // }
133
-
134
- // return handler(context, serviceInjections).then((result) => {
135
- // runtime.cache.set(cacheHashKey, result, action.cache.ttl)
136
- // return result
137
- // })
138
- // })
139
- // }
140
- // }
141
- // return handler
142
- // }
143
- // }
144
- // }
145
-
146
135
  return cache
147
136
  }
package/lib/index.js CHANGED
@@ -45,17 +45,16 @@ exports.Errors = require('./errors')
45
45
 
46
46
  exports.Constants = require('./constants')
47
47
 
48
- // Transport
49
- exports.TransportAdapters = require('./transport/adapters')
50
-
51
48
  // Caching
52
- exports.Cache = require('./cache')
49
+ exports.Cache = require('./cache/adapters')
53
50
 
54
51
  /**
55
52
  * @deprecated since version 0.10.0
56
53
  */
57
54
  exports.createBaseTracingCollector = require('./tracing/collectors/base').createBaseTracingCollector
55
+ exports.TransportAdapters = require('./transport/adapters')
58
56
  exports.TracingAdapters = require('./tracing/collectors')
57
+ exports.CacheAdapters = require('./cache/adapters')
59
58
 
60
59
  // Helper
61
60
  exports.defineBrokerOptions = require('./helper/defineBrokerOptions')
@@ -1,36 +1,62 @@
1
- const { isObject } = 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 = Object.assign(
7
- isObject(action.cache) ? action.cache : { enabled: !!action.cache },
8
- runtime.options.cache
9
- )
10
- if (cacheOptions.enabled) {
6
+ const cacheOptions = runtime.options.cache
7
+ const cacheActionOptions = {
8
+ enabled: !!action.cache
9
+ }
10
+
11
+ if (isString(action.cache)) {
12
+ cacheActionOptions.keys = action.cache.split(' ')
13
+ } else if (action.cache && Array.isArray(action.cache.keys)) {
14
+ cacheActionOptions.keys = action.cache.keys
15
+ }
16
+
17
+ if (cacheActionOptions.enabled) {
18
+ const cache = runtime.cache
19
+ const isEnabledFunction = isFunction(action.cache.condition)
20
+
11
21
  return function cacheMiddleware (context, serviceInjections) {
12
- const cache = runtime.cache
13
- const cacheHashKey = cache.getCachingHash(action.name, context.data, context.meta, action.cache.keys)
22
+ // handle enabled function
23
+ if (isEnabledFunction) {
24
+ if (!action.cache.enabled.call(null, context)) {
25
+ // Enabled function returns "false". Cache is disabled.
26
+ return handler(context, serviceInjections)
27
+ }
28
+ }
29
+
30
+ // Generate cache hash
31
+ const cacheHashKey = cache.getCachingKey(
32
+ action.name,
33
+ context.data,
34
+ context.meta,
35
+ cacheActionOptions.keys
36
+ )
37
+
14
38
  context.isCachedResult = false
15
39
 
40
+ // Disable caching by meta property.
16
41
  if (context.meta.$noCache === true) {
17
42
  return handler(context, serviceInjections)
18
43
  }
19
44
 
45
+ // The cache adapter is not connected yet. In this case, we call the handler regular
20
46
  if (cache.isConnected === false) {
21
47
  cache.log('Cache adapter is not connected yet. Call handler...')
22
48
  return handler(context, serviceInjections)
23
49
  }
24
50
 
25
51
  if (cacheOptions.lock.enabled) {
26
- let cacheProm
52
+ let cachePromise
27
53
  if (cacheOptions.lock.staleTime && cache.getWithTTl) {
28
54
 
29
55
  } else {
30
- cacheProm = runtime.cache.get(cacheHashKey)
56
+ cachePromise = runtime.cache.get(cacheHashKey)
31
57
  }
32
58
 
33
- return cacheProm.then((cachedResult) => {
59
+ return cachePromise.then((cachedResult) => {
34
60
  if (cachedResult !== null) {
35
61
  // Found a cached value. Skip calling handler and return our value
36
62
  context.isCachedResult = true
@@ -147,19 +147,22 @@ exports.createRegistry = (runtime) => {
147
147
 
148
148
  // remove old services
149
149
  const oldServices = Array.from(this.serviceCollection.services)
150
- oldServices.forEach((service) => {
151
- if (service.node.id !== node.id) return
150
+ oldServices.forEach((oldService) => {
151
+ if (oldService.node.id !== node.id) {
152
+ return
153
+ }
152
154
 
153
155
  let isExisting = false
154
156
 
157
+ // check if the old service exists in the new services.
155
158
  services.forEach((svc) => {
156
- if (service.equals(svc.name, svc.version)) {
159
+ if (oldService.equals(svc.name, svc.version)) {
157
160
  isExisting = true
158
161
  }
159
162
  })
160
163
 
161
164
  if (!isExisting) {
162
- this.deregisterService(service.name, service.version, node.id)
165
+ this.deregisterService(oldService.name, oldService.version, node.id)
163
166
  }
164
167
  })
165
168
 
@@ -186,9 +189,9 @@ exports.createRegistry = (runtime) => {
186
189
  }
187
190
 
188
191
  if (node.isLocal) {
189
- action.handler = middlewareHandler.wrapHandler('localAction', action.handler, action)// this.onRegisterLocalAction(action)
192
+ action.handler = middlewareHandler.wrapHandler('localAction', action.handler, action)
190
193
  } else {
191
- action.handler = middlewareHandler.wrapHandler('remoteAction', runtime.transport.sendRequest.bind(runtime.transport), action)// this.onRegisterRemoteAction(action)
194
+ action.handler = middlewareHandler.wrapHandler('remoteAction', runtime.transport.sendRequest.bind(runtime.transport), action)
192
195
  }
193
196
 
194
197
  this.actionCollection.add(node, service, action)
@@ -196,13 +199,10 @@ exports.createRegistry = (runtime) => {
196
199
  service.addAction(action)
197
200
  })
198
201
  },
199
- getActionList (options) {
200
- return this.actionCollection.list(options)
201
- },
202
202
  deregisterService (name, version, nodeId) {
203
203
  this.serviceCollection.remove(nodeId || runtime.nodeId, name, version)
204
204
 
205
- // It must be a local service
205
+ // It must be a local service if there is no node ID.
206
206
  if (!nodeId) {
207
207
  const serviceToRemove = this.nodeCollection.localNode.services.find(service => service.name === name)
208
208
  this.nodeCollection.localNode.services.splice(this.nodeCollection.localNode.services.indexOf(serviceToRemove), 1)
@@ -386,12 +386,6 @@ exports.createRegistry = (runtime) => {
386
386
  this.nodeCollection.remove(nodeId)
387
387
  runtime.eventBus.broadcastLocal('$node.removed', { nodeId })
388
388
  this.log.warn(`Node "${nodeId}" removed.`)
389
- },
390
- getNodeList (options) {
391
- return this.nodeCollection.list(options)
392
- },
393
- getServiceList (options) {
394
- return this.serviceCollection.list(options)
395
389
  }
396
390
  }
397
391
 
@@ -1,10 +1,19 @@
1
- const Cache = require('../cache')
1
+ const { isFunction } = require('@weave-js/utils')
2
+ const { WeaveError } = require('../errors')
2
3
 
3
4
  exports.initCache = (runtime) => {
4
5
  if (runtime.options.cache && runtime.options.cache.enabled) {
5
- const createCache = Cache.resolve(runtime.options.cache.adapter)
6
+ if (!isFunction(runtime.options.cache.adapter)) {
7
+ throw new WeaveError('Invalid cache adapter.')
8
+ }
9
+
10
+ // Init cache adapter
11
+ const cache = runtime.options.cache.adapter(runtime, runtime.options.cache)
12
+
13
+ runtime.log.info(`Cache: ${cache.name}`)
14
+
6
15
  Object.defineProperty(runtime, 'cache', {
7
- value: createCache(runtime, runtime.options.cache)
16
+ value: cache
8
17
  })
9
18
  }
10
19
  }
package/lib/types.js CHANGED
@@ -22,7 +22,7 @@ const { EventEmitter2: EventEmitter } = require('eventemitter2')
22
22
  /**
23
23
  * @callback CallActionFunctionDef - Action function definition
24
24
  * @param {string} actionName - Name of the action
25
- * @param {object} data - Payload
25
+ * @param {object} [data] - Payload
26
26
  * @param {ActionOptions} [options] - Action options
27
27
  * @return {Promise<any>} Promise - Result
28
28
  */
@@ -127,7 +127,7 @@ const { EventEmitter2: EventEmitter } = require('eventemitter2')
127
127
  * @property {function(string, any, any=):Promise<any>} emit - Emit
128
128
  * @property {function(string, any, any=):Promise<any>} broadcast broadcast
129
129
  * @property {function(string, any, any=):Promise<any>} broadcastLocal broadcastLocal
130
- * @property {function(string):Promise<any>} waitForServices waitForServices
130
+ * @property {function(Array<string>|string):Promise<any>} waitForServices waitForServices
131
131
  * @property {function(string, number=):Promise<PingResult>} ping ping
132
132
  * @property {function(Error):void} handleError handleError
133
133
  * @property {function():void} fatalError fatalError
@@ -169,7 +169,13 @@ const { EventEmitter2: EventEmitter } = require('eventemitter2')
169
169
  * @property {Boolean} enabled - Enable tracing middleware. (default = false)
170
170
  * @property {Number} samplingRate - Rate of traced actions. (default = 1.0)
171
171
  * @property {Array<String|Object>} collectors - Array of tracing collectors.
172
- * @property {TracingErrorOptions} errors - Settings for tracing errors.
172
+ * @property {TracingErrorOptions} [errors] - Settings for tracing errors.
173
+ */
174
+
175
+ /**
176
+ * Configuration object for weave service broker.
177
+ * @typedef {Object} CacheLockOptions
178
+ * @property {Boolean} [enabled=false] Enable cache lock. (default = false)
173
179
  */
174
180
 
175
181
  /**
@@ -178,6 +184,7 @@ const { EventEmitter2: EventEmitter } = require('eventemitter2')
178
184
  * @property {Boolean} enabled Enable cache middleware. (default = false)
179
185
  * @property {String | Object} adapter - Cache adapter. (default = memory (In Memory))
180
186
  * @property {number} [ttl=3000] - Cache item TTL.
187
+ * @property {CacheLockOptions} [lock] Cache lock options.
181
188
  */
182
189
 
183
190
  /**
@@ -328,7 +335,7 @@ const { EventEmitter2: EventEmitter } = require('eventemitter2')
328
335
  * @property {number} stopTime stopTime
329
336
  * @property {any} [metrics] metrics
330
337
  * @property {function(any):void} setData - Set data object.
331
- * @property {function(string, any, ActionOptions):ContextPromise} call - Call a service action
338
+ * @property {CallActionFunctionDef} call - Call a service action
332
339
  * @property {function(string, object):Promise<any>} emit emit
333
340
  * @property {Stream} [stream] - Stream
334
341
  * @property {function(string, any):Promise<any>} broadcast Broadcast an event to all listener.
@@ -350,7 +357,7 @@ const { EventEmitter2: EventEmitter } = require('eventemitter2')
350
357
  * @property {Promise<any>} get get
351
358
  * @property {Promise<any>} remove remove
352
359
  * @property {Promise<any>} clear clear
353
- * @property {string} getCachingHash getCachingHash
360
+ * @property {string} getCachingKey getCachingKey
354
361
  * @property {function():Middleware} createMiddleware createMiddleware
355
362
  * @property {function():Promise<any>} stop stop
356
363
  */
@@ -482,7 +489,7 @@ const { EventEmitter2: EventEmitter } = require('eventemitter2')
482
489
  * @property {function(string):Endpoint} getLocalActionEndpoint getLocalActionEndpoint
483
490
  * @property {function():NodeInfo} getNodeInfo getNodeInfo
484
491
  * @property {function():NodeInfo} getLocalNodeInfo getLocalNodeInfo
485
- * @property {function():NodeInfo} generateLocalNodeInfo generateLocalNodeInfo
492
+ * @property {function(Boolean=):NodeInfo} generateLocalNodeInfo generateLocalNodeInfo
486
493
  * @property {*} processNodeInfo processNodeInfo
487
494
  * @property {function(string, boolean):void} nodeDisconnected nodeDisconnected
488
495
  * @property {function(string):void} removeNode removeNode
@@ -507,6 +514,7 @@ const { EventEmitter2: EventEmitter } = require('eventemitter2')
507
514
  * @property {function():number} count count
508
515
  * @property {function(string):Endpoint} getByNodeId getByNodeId
509
516
  * @property {function(string):void} removeByNodeId removeByNodeId
517
+ * @property {function(string):Endpoint} endpointByNodeId Get endpoint by node ID.
510
518
  * @property {function():void} removeByService removeByService
511
519
  */
512
520
 
@@ -522,6 +530,7 @@ const { EventEmitter2: EventEmitter } = require('eventemitter2')
522
530
  * @property {number} lastHeartbeatTime lastHeartbeatTime
523
531
  * @property {number} offlineTime offlineTime
524
532
  * @property {boolean} isAvailable isAvailable
533
+ * @property {boolean} wasDisconnectedUnexpectedly Node was disconnected unexpectedly
525
534
  * @property {Array<ServiceItem>} services services
526
535
  * @property {number} sequence sequence
527
536
  * @property {Array<string>} [events] events
@@ -561,7 +570,8 @@ const { EventEmitter2: EventEmitter } = require('eventemitter2')
561
570
 
562
571
  /**
563
572
  * @typedef {object} NodeCollectionListFilterOptions
564
- * @property {boolean} [withServices=true] Output all services on an node.
573
+ * @property {boolean} [availableOnly=false] Git only available nodes.
574
+ * @property {boolean} [withServices=false] Output all services on an node.
565
575
  */
566
576
 
567
577
  /**
@@ -575,14 +585,14 @@ const { EventEmitter2: EventEmitter } = require('eventemitter2')
575
585
  * @property {boolean} has has
576
586
  * @property {function(string):Node} get get
577
587
  * @property {function(string):boolean} remove remove
578
- * @property {function(NodeCollectionListFilterOptions):Array<Node>} list list
588
+ * @property {function(NodeCollectionListFilterOptions=):Array<Node>} list list
579
589
  * @property {void} disconnected disconnected
580
590
  * @property {Array<Node>} toArray toArray
581
591
  */
582
592
 
583
593
  /**
584
594
  * @typedef {Object} ServiceActionCollectionListFilterParams
585
- * @property {boolean} [onlyLocals] Shows only local service actions
595
+ * @property {boolean} [localOnly] Shows only local service actions
586
596
  * @property {boolean} [skipInternals] Shows only local service actions
587
597
  * @property {boolean} [withEndpoints] Shows only local service actions
588
598
  */
@@ -617,6 +627,7 @@ const { EventEmitter2: EventEmitter } = require('eventemitter2')
617
627
  /**
618
628
  * @typedef {Object} ServiceCollectionListFilterParams
619
629
  * @property {boolean} [localOnly=false] Show only local services.
630
+ * @property {boolean} [availableOnly=false] Show only available services.
620
631
  * @property {boolean} [withActions=false] Include actions in result.
621
632
  * @property {boolean} [withEvents=false] Include events in result.
622
633
  * @property {boolean} [withNodeService=false] Include node service.
@@ -630,8 +641,8 @@ const { EventEmitter2: EventEmitter } = require('eventemitter2')
630
641
  * @property {function(Node,string, number, any):ServiceItem} add Add a new service to service collection.
631
642
  * @property {*} get get
632
643
  * @property {function(string, number, string):boolean} has has
633
- * @property {function(string, string, number):void} remove remove
634
- * @property {function(string):void} removeAllByNodeId removeAllByNodeId
644
+ * @property {function(string, string, number=):void} remove Remove endpoint by node ID, service name and version*.
645
+ * @property {function(string):void} removeAllByNodeId Remove all endpoints by node ID.
635
646
  * @property {*} registerAction registerAction
636
647
  * @property {function(string):EndpointCollection} tryFindActionsByActionName tryFindActionsByActionName
637
648
  * @property {function():Array<any>} getActionsList getActionsList
@@ -1,5 +1,5 @@
1
1
 
2
2
  exports = {
3
3
  ...require('./options'),
4
- ...require('./restore-error')
4
+ ...require('./restoreError')
5
5
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weave-js/core",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "The core package of weave",
5
5
  "keywords": [
6
6
  "Weave",
@@ -40,8 +40,8 @@
40
40
  "license": "MIT",
41
41
  "dependencies": {
42
42
  "@weave-js/errors": "^0.9.1",
43
- "@weave-js/utils": "^0.10.0",
44
- "@weave-js/validator": "^0.11.0",
43
+ "@weave-js/utils": "^0.10.1",
44
+ "@weave-js/validator": "^0.11.1",
45
45
  "eventemitter2": "^6.4.5",
46
46
  "glob": "^7.2.0"
47
47
  },
@@ -49,5 +49,5 @@
49
49
  "lib": "lib",
50
50
  "test": "test"
51
51
  },
52
- "gitHead": "84fd5e4af3af96e8c004bcfba40bb3cb35f23fa7"
52
+ "gitHead": "bc467dd08fe0626c40e7eb19b344c102386baf15"
53
53
  }
@@ -1,48 +0,0 @@
1
- /*
2
- * Author: Kevin Ries (kevin@fachw3rk.de)
3
- * -----
4
- * Copyright 2021 Fachwerk
5
- */
6
-
7
- const { isString, isFunction } = require('@weave-js/utils')
8
- const { WeaveBrokerOptionsError } = require('../errors')
9
-
10
- const adapters = {
11
- Memory: require('./inMemory')
12
- }
13
-
14
- exports.adapters = adapters
15
-
16
- exports.createCacheBase = require('./base').createCacheBase
17
-
18
- exports.resolve = (cacheOptions) => {
19
- const getByName = name => {
20
- if (!name) {
21
- return null
22
- }
23
-
24
- const n = Object.keys(adapters).find(n => n.toLowerCase() === name.toLowerCase())
25
- if (n) {
26
- return adapters[n]
27
- }
28
- }
29
-
30
- let cacheFactory
31
-
32
- if (cacheOptions === true) {
33
- cacheFactory = this.adapters.Memory
34
- } else if (isString(cacheOptions)) {
35
- const cache = getByName(cacheOptions)
36
-
37
- if (cache) {
38
- cacheFactory = cache
39
- } else {
40
- throw new WeaveBrokerOptionsError(`Unknown cache type "${cacheOptions}"`)
41
- }
42
- } else if (isFunction(cacheOptions)) {
43
- cacheFactory = cacheOptions
44
- }
45
- if (cacheFactory) {
46
- return cacheFactory
47
- }
48
- }