@mojaloop/central-services-shared 18.22.3 → 18.22.4
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/CHANGELOG.md +7 -0
- package/audit-ci.jsonc +1 -0
- package/package.json +2 -2
- package/src/util/endpoints.js +29 -18
- package/src/util/participants.js +30 -24
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### [18.22.4](https://github.com/mojaloop/central-services-shared/compare/v18.22.3...v18.22.4) (2025-03-13)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Chore
|
|
9
|
+
|
|
10
|
+
* **csi-1233:** improved participantEndpointCache logging ([#440](https://github.com/mojaloop/central-services-shared/issues/440)) ([94eb898](https://github.com/mojaloop/central-services-shared/commit/94eb898a0d3cb9152390162d5fefca24a6c6082e))
|
|
11
|
+
|
|
5
12
|
### [18.22.3](https://github.com/mojaloop/central-services-shared/compare/v18.22.2...v18.22.3) (2025-03-12)
|
|
6
13
|
|
|
7
14
|
|
package/audit-ci.jsonc
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mojaloop/central-services-shared",
|
|
3
|
-
"version": "18.22.
|
|
3
|
+
"version": "18.22.4",
|
|
4
4
|
"description": "Shared code for mojaloop central services",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "ModusBox",
|
|
@@ -85,7 +85,7 @@
|
|
|
85
85
|
"yaml": "2.7.0"
|
|
86
86
|
},
|
|
87
87
|
"devDependencies": {
|
|
88
|
-
"@mojaloop/sdk-standard-components": "19.10.
|
|
88
|
+
"@mojaloop/sdk-standard-components": "19.10.3",
|
|
89
89
|
"@types/hapi__joi": "17.1.15",
|
|
90
90
|
"audit-ci": "7.1.0",
|
|
91
91
|
"base64url": "3.0.1",
|
package/src/util/endpoints.js
CHANGED
|
@@ -29,7 +29,6 @@
|
|
|
29
29
|
|
|
30
30
|
'use strict'
|
|
31
31
|
|
|
32
|
-
const Logger = require('@mojaloop/central-services-logger')
|
|
33
32
|
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
|
34
33
|
const Metrics = require('@mojaloop/central-services-metrics')
|
|
35
34
|
const proxyLib = require('@mojaloop/inter-scheme-proxy-cache-lib')
|
|
@@ -38,6 +37,7 @@ const CatboxMemory = require('@hapi/catbox-memory')
|
|
|
38
37
|
const Mustache = require('mustache')
|
|
39
38
|
const { Map } = require('immutable')
|
|
40
39
|
|
|
40
|
+
const logger = require('../logger').logger.child({ component: 'participantEndpointCache' })
|
|
41
41
|
const Enum = require('../enums')
|
|
42
42
|
const Http = require('./http')
|
|
43
43
|
const request = require('./request')
|
|
@@ -66,8 +66,9 @@ const fetchEndpoints = async (fsp) => {
|
|
|
66
66
|
'fetchParticipants - Metrics for fetchParticipants',
|
|
67
67
|
['success']
|
|
68
68
|
).startTimer()
|
|
69
|
+
const log = logger.child({ fsp, method: 'fetchEndpoints' })
|
|
69
70
|
try {
|
|
70
|
-
|
|
71
|
+
log.debug('refreshing the cache for FSP')
|
|
71
72
|
if (!hubName) {
|
|
72
73
|
throw Error('"hubName" is not initialized. Initialize the cache first.')
|
|
73
74
|
}
|
|
@@ -76,7 +77,8 @@ const fetchEndpoints = async (fsp) => {
|
|
|
76
77
|
}
|
|
77
78
|
const defaultHeaders = Http.SwitchDefaultHeaders(hubName, Enum.Http.HeaderResources.PARTICIPANTS, hubName)
|
|
78
79
|
const url = Mustache.render(switchEndpoint + Enum.EndPoints.FspEndpointTemplates.PARTICIPANT_ENDPOINTS_GET, { fsp })
|
|
79
|
-
|
|
80
|
+
log.verbose('url for PARTICIPANT_ENDPOINTS_GET', { url })
|
|
81
|
+
|
|
80
82
|
const response = await request.sendRequest({
|
|
81
83
|
url,
|
|
82
84
|
headers: defaultHeaders,
|
|
@@ -84,8 +86,9 @@ const fetchEndpoints = async (fsp) => {
|
|
|
84
86
|
destination: hubName,
|
|
85
87
|
hubNameRegex
|
|
86
88
|
})
|
|
87
|
-
Logger.isDebugEnabled && Logger.debug(`[fsp=${fsp}] ~ Model::participantEndpoint::fetchEndpoints := successful with body: ${JSON.stringify(response.data)}`)
|
|
88
89
|
const endpoints = response.data
|
|
90
|
+
log.debug('fetchEndpoints raw response.data:', { endpoints })
|
|
91
|
+
|
|
89
92
|
const endpointMap = {}
|
|
90
93
|
if (Array.isArray(endpoints)) {
|
|
91
94
|
endpoints.forEach(item => {
|
|
@@ -93,12 +96,12 @@ const fetchEndpoints = async (fsp) => {
|
|
|
93
96
|
endpointMap[item.type] = item.value
|
|
94
97
|
})
|
|
95
98
|
}
|
|
96
|
-
|
|
99
|
+
log.verbose('fetchEndpoints is done', { endpointMap })
|
|
97
100
|
histTimer({ success: true })
|
|
101
|
+
|
|
98
102
|
return endpointMap
|
|
99
|
-
} catch (
|
|
100
|
-
|
|
101
|
-
Logger.isErrorEnabled && Logger.error(`participantEndpointCache::fetchEndpoints:: ERROR:'${e}'`)
|
|
103
|
+
} catch (err) {
|
|
104
|
+
log.error('error in fetchEndpoints: ', err)
|
|
102
105
|
}
|
|
103
106
|
}
|
|
104
107
|
|
|
@@ -116,18 +119,17 @@ const fetchEndpoints = async (fsp) => {
|
|
|
116
119
|
*/
|
|
117
120
|
exports.initializeCache = async (policyOptions, config) => {
|
|
118
121
|
try {
|
|
119
|
-
|
|
122
|
+
logger.debug('initializeCache start', { clientOptions, policyOptions })
|
|
120
123
|
client = new Catbox.Client(CatboxMemory, clientOptions)
|
|
121
124
|
await client.start()
|
|
122
125
|
policyOptions.generateFunc = fetchEndpoints
|
|
123
|
-
Logger.isDebugEnabled && Logger.debug(`participantEndpointCache::initializeCache::start::policyOptions - ${JSON.stringify(policyOptions)}`)
|
|
124
126
|
policy = new Catbox.Policy(policyOptions, client, partition)
|
|
125
|
-
Logger.isDebugEnabled && Logger.debug('participantEndpointCache::initializeCache::Cache initialized successfully')
|
|
126
127
|
hubName = config.hubName
|
|
127
128
|
hubNameRegex = config.hubNameRegex
|
|
129
|
+
logger.verbose('initializeCache is done successfully', { hubName, hubNameRegex })
|
|
128
130
|
return true
|
|
129
131
|
} catch (err) {
|
|
130
|
-
|
|
132
|
+
logger.error('error in initializeCache: ', err)
|
|
131
133
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
132
134
|
}
|
|
133
135
|
}
|
|
@@ -152,9 +154,11 @@ exports.getEndpoint = async (switchUrl, fsp, endpointType, options = {}, renderO
|
|
|
152
154
|
['success', 'hit']
|
|
153
155
|
).startTimer()
|
|
154
156
|
switchEndpoint = switchUrl
|
|
155
|
-
|
|
157
|
+
const log = logger.child({ fsp, endpointType, method: 'getEndpoint' })
|
|
158
|
+
log.debug('getEndpoint start', { switchUrl })
|
|
156
159
|
let proxyId
|
|
157
160
|
const result = url => proxyConfig?.enabled ? { url, proxyId } : url
|
|
161
|
+
|
|
158
162
|
try {
|
|
159
163
|
// If a service passes in `getDecoratedValue` as true, then an object
|
|
160
164
|
// { value, cached, report } is returned, where value is the cached value,
|
|
@@ -168,7 +172,11 @@ exports.getEndpoint = async (switchUrl, fsp, endpointType, options = {}, renderO
|
|
|
168
172
|
proxyId = await proxy.lookupProxyByDfspId(fsp)
|
|
169
173
|
endpoints = proxyId && await policy.get(proxyId)
|
|
170
174
|
}
|
|
171
|
-
if (!endpoints)
|
|
175
|
+
if (!endpoints) {
|
|
176
|
+
log.warn('no endpoints found for fsp')
|
|
177
|
+
throw ErrorHandler.CreateFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PARTY_NOT_FOUND)
|
|
178
|
+
}
|
|
179
|
+
|
|
172
180
|
if ('value' in endpoints && 'cached' in endpoints) {
|
|
173
181
|
if (endpoints.cached === null) {
|
|
174
182
|
histTimer({ success: true, hit: false })
|
|
@@ -182,6 +190,7 @@ exports.getEndpoint = async (switchUrl, fsp, endpointType, options = {}, renderO
|
|
|
182
190
|
}
|
|
183
191
|
return result(Mustache.render(endpoint, options))
|
|
184
192
|
}
|
|
193
|
+
|
|
185
194
|
let endpoint = new Map(endpoints).get(endpointType)
|
|
186
195
|
if (renderOptions.path) {
|
|
187
196
|
endpoint = (endpoint === undefined) ? endpoint : endpoint + renderOptions.path
|
|
@@ -190,7 +199,7 @@ exports.getEndpoint = async (switchUrl, fsp, endpointType, options = {}, renderO
|
|
|
190
199
|
return result(Mustache.render(endpoint, options))
|
|
191
200
|
} catch (err) {
|
|
192
201
|
histTimer({ success: false, hit: false })
|
|
193
|
-
|
|
202
|
+
log.error('error in getEndpoint: ', err)
|
|
194
203
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
195
204
|
}
|
|
196
205
|
}
|
|
@@ -215,7 +224,8 @@ exports.getEndpointAndRender = async (switchUrl, fsp, endpointType, path = '', o
|
|
|
215
224
|
['success']
|
|
216
225
|
).startTimer()
|
|
217
226
|
switchEndpoint = switchUrl
|
|
218
|
-
|
|
227
|
+
const log = logger.child({ fsp, endpointType })
|
|
228
|
+
log.debug('getEndpointAndRender start', { switchUrl, path })
|
|
219
229
|
|
|
220
230
|
try {
|
|
221
231
|
const endpoint = exports.getEndpoint(switchUrl, fsp, endpointType, options, { path })
|
|
@@ -223,7 +233,7 @@ exports.getEndpointAndRender = async (switchUrl, fsp, endpointType, path = '', o
|
|
|
223
233
|
return endpoint
|
|
224
234
|
} catch (err) {
|
|
225
235
|
histTimer({ success: false })
|
|
226
|
-
|
|
236
|
+
log.error('error in getEndpointAndRender: ', err)
|
|
227
237
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
228
238
|
}
|
|
229
239
|
}
|
|
@@ -236,7 +246,7 @@ exports.getEndpointAndRender = async (switchUrl, fsp, endpointType, path = '', o
|
|
|
236
246
|
* @returns {boolean} - Returns the status
|
|
237
247
|
*/
|
|
238
248
|
exports.stopCache = async () => {
|
|
239
|
-
|
|
249
|
+
logger.verbose('stopping the cache')
|
|
240
250
|
if (client) {
|
|
241
251
|
return client.stop()
|
|
242
252
|
}
|
|
@@ -252,6 +262,7 @@ exports.stopCache = async () => {
|
|
|
252
262
|
exports.stopProxy = async () => {
|
|
253
263
|
const result = await proxy?.disconnect()
|
|
254
264
|
proxy = undefined
|
|
265
|
+
logger.verbose('proxy disconnected')
|
|
255
266
|
return result
|
|
256
267
|
}
|
|
257
268
|
|
package/src/util/participants.js
CHANGED
|
@@ -28,17 +28,19 @@
|
|
|
28
28
|
|
|
29
29
|
'use strict'
|
|
30
30
|
|
|
31
|
-
const
|
|
31
|
+
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
|
32
|
+
const Metrics = require('@mojaloop/central-services-metrics')
|
|
32
33
|
const Catbox = require('@hapi/catbox')
|
|
33
34
|
const CatboxMemory = require('@hapi/catbox-memory')
|
|
34
|
-
const
|
|
35
|
+
const Mustache = require('mustache')
|
|
36
|
+
|
|
37
|
+
const logger = require('../logger').logger.child({ component: 'participantCache' })
|
|
35
38
|
const Enum = require('../enums')
|
|
39
|
+
const Http = require('./http')
|
|
40
|
+
const request = require('./request')
|
|
41
|
+
|
|
36
42
|
const partition = 'participant-cache'
|
|
37
43
|
const clientOptions = { partition }
|
|
38
|
-
const Mustache = require('mustache')
|
|
39
|
-
const request = require('./request')
|
|
40
|
-
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
|
41
|
-
const Metrics = require('@mojaloop/central-services-metrics')
|
|
42
44
|
|
|
43
45
|
let client
|
|
44
46
|
let policy
|
|
@@ -61,8 +63,10 @@ const fetchParticipant = async (fsp) => {
|
|
|
61
63
|
'fetchParticipant - Metrics for fetchParticipant',
|
|
62
64
|
['success']
|
|
63
65
|
).startTimer()
|
|
66
|
+
const log = logger.child({ fsp, method: 'fetchParticipant' })
|
|
67
|
+
|
|
64
68
|
try {
|
|
65
|
-
|
|
69
|
+
log.debug('refreshing participant cache', { hubName })
|
|
66
70
|
if (!hubName) {
|
|
67
71
|
throw Error('"hubName" is not initialized. Initialize the cache first.')
|
|
68
72
|
}
|
|
@@ -71,7 +75,8 @@ const fetchParticipant = async (fsp) => {
|
|
|
71
75
|
}
|
|
72
76
|
const defaultHeaders = Http.SwitchDefaultHeaders(hubName, Enum.Http.HeaderResources.PARTICIPANTS, hubName)
|
|
73
77
|
const url = Mustache.render(switchEndpoint + Enum.EndPoints.FspEndpointTemplates.PARTICIPANTS_GET, { fsp })
|
|
74
|
-
|
|
78
|
+
log.verbose('url for PARTICIPANTS_GET', { url })
|
|
79
|
+
|
|
75
80
|
const response = await request.sendRequest({
|
|
76
81
|
url,
|
|
77
82
|
headers: defaultHeaders,
|
|
@@ -80,12 +85,14 @@ const fetchParticipant = async (fsp) => {
|
|
|
80
85
|
hubNameRegex
|
|
81
86
|
})
|
|
82
87
|
const participant = response.data
|
|
88
|
+
log.verbose('fetchParticipant is done', { participant })
|
|
83
89
|
histTimer({ success: true })
|
|
90
|
+
|
|
84
91
|
return participant
|
|
85
|
-
} catch (
|
|
92
|
+
} catch (err) {
|
|
86
93
|
histTimer({ success: false })
|
|
87
94
|
// We're logging this as a "warning" rather than "error" because the participant might be a proxied participant
|
|
88
|
-
|
|
95
|
+
log.warn('error in fetchParticipants: ', err)
|
|
89
96
|
}
|
|
90
97
|
}
|
|
91
98
|
|
|
@@ -99,18 +106,17 @@ const fetchParticipant = async (fsp) => {
|
|
|
99
106
|
*/
|
|
100
107
|
exports.initializeCache = async (policyOptions, config) => {
|
|
101
108
|
try {
|
|
102
|
-
|
|
109
|
+
logger.debug('participantCache::initializeCache start', { clientOptions, policyOptions })
|
|
103
110
|
client = new Catbox.Client(CatboxMemory, clientOptions)
|
|
104
111
|
await client.start()
|
|
105
112
|
policyOptions.generateFunc = fetchParticipant
|
|
106
|
-
Logger.isDebugEnabled && Logger.debug(`participantCache::initializeCache::start::policyOptions - ${JSON.stringify(policyOptions)}`)
|
|
107
113
|
policy = new Catbox.Policy(policyOptions, client, partition)
|
|
108
|
-
Logger.isDebugEnabled && Logger.debug('participantCache::initializeCache::Cache initialized successfully')
|
|
109
114
|
hubName = config.hubName
|
|
110
115
|
hubNameRegex = config.hubNameRegex
|
|
116
|
+
logger.verbose('participantCache::initializeCache is done', { hubName })
|
|
111
117
|
return true
|
|
112
118
|
} catch (err) {
|
|
113
|
-
|
|
119
|
+
logger.error(`error in participantCache::initializeCache: ${err?.message}`, err)
|
|
114
120
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
115
121
|
}
|
|
116
122
|
}
|
|
@@ -132,7 +138,8 @@ exports.getParticipant = async (switchUrl, fsp) => {
|
|
|
132
138
|
['success', 'hit']
|
|
133
139
|
).startTimer()
|
|
134
140
|
switchEndpoint = switchUrl
|
|
135
|
-
|
|
141
|
+
const log = logger.child({ fsp, method: 'getParticipant' })
|
|
142
|
+
log.debug('getParticipant start', { switchUrl })
|
|
136
143
|
try {
|
|
137
144
|
// If a service passes in `getDecoratedValue` as true, then an object
|
|
138
145
|
// { value, cached, report } is returned, where value is the cached value,
|
|
@@ -140,11 +147,7 @@ exports.getParticipant = async (switchUrl, fsp) => {
|
|
|
140
147
|
let participant = await policy.get(fsp)
|
|
141
148
|
|
|
142
149
|
if ('value' in participant && 'cached' in participant) {
|
|
143
|
-
|
|
144
|
-
histTimer({ success: true, hit: false })
|
|
145
|
-
} else {
|
|
146
|
-
histTimer({ success: true, hit: true })
|
|
147
|
-
}
|
|
150
|
+
histTimer({ success: true, hit: participant.cached !== null })
|
|
148
151
|
participant = participant.value
|
|
149
152
|
} else {
|
|
150
153
|
histTimer({ success: true, hit: false })
|
|
@@ -152,9 +155,10 @@ exports.getParticipant = async (switchUrl, fsp) => {
|
|
|
152
155
|
|
|
153
156
|
/* istanbul ignore next */
|
|
154
157
|
if (!participant) {
|
|
155
|
-
|
|
158
|
+
log.warn('no participant found')
|
|
156
159
|
return null
|
|
157
160
|
}
|
|
161
|
+
log.verbose('getParticipant result:', { participant })
|
|
158
162
|
|
|
159
163
|
if (participant.errorInformation) {
|
|
160
164
|
// Drop error from cache
|
|
@@ -164,7 +168,7 @@ exports.getParticipant = async (switchUrl, fsp) => {
|
|
|
164
168
|
return participant
|
|
165
169
|
} catch (err) {
|
|
166
170
|
histTimer({ success: false, hit: false })
|
|
167
|
-
|
|
171
|
+
log.error('error in getParticipant: ', err)
|
|
168
172
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
169
173
|
}
|
|
170
174
|
}
|
|
@@ -176,8 +180,9 @@ exports.getParticipant = async (switchUrl, fsp) => {
|
|
|
176
180
|
*
|
|
177
181
|
* @returns {void}
|
|
178
182
|
*/
|
|
183
|
+
/* istanbul ignore next */
|
|
179
184
|
exports.invalidateParticipantCache = async (fsp) => {
|
|
180
|
-
|
|
185
|
+
logger.verbose('participantCache invalidateParticipantCache')
|
|
181
186
|
if (policy) {
|
|
182
187
|
return policy.drop(fsp)
|
|
183
188
|
}
|
|
@@ -190,8 +195,9 @@ exports.invalidateParticipantCache = async (fsp) => {
|
|
|
190
195
|
*
|
|
191
196
|
* @returns {boolean} - Returns the status
|
|
192
197
|
*/
|
|
198
|
+
/* istanbul ignore next */
|
|
193
199
|
exports.stopCache = async () => {
|
|
194
|
-
|
|
200
|
+
logger.verbose('participantCache stopCache')
|
|
195
201
|
if (client) {
|
|
196
202
|
return client.stop()
|
|
197
203
|
}
|