account-lookup-service 17.1.0 → 17.2.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/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
+ ## [17.2.0](https://github.com/mojaloop/account-lookup-service/compare/v17.1.0...v17.2.0) (2025-02-26)
6
+
7
+
8
+ ### Features
9
+
10
+ * update count metrics, fix int, update oracle code null currency ([#526](https://github.com/mojaloop/account-lookup-service/issues/526)) ([62167a5](https://github.com/mojaloop/account-lookup-service/commit/62167a5357b800af93bc0c4d950c0efbc6850a82))
11
+
5
12
  ## [17.1.0](https://github.com/mojaloop/account-lookup-service/compare/v17.0.3...v17.1.0) (2025-02-20)
6
13
 
7
14
 
@@ -46,10 +46,15 @@ services:
46
46
  command:
47
47
  - "sh"
48
48
  - "-c"
49
- - "sh /opt/wait-for/wait-for-account-lookup-service.sh && node src/index.js server"
49
+ - "npm run start:apiAndAdmin"
50
50
  ports:
51
51
  - "4001:4001"
52
52
  - "4002:4002"
53
+ depends_on:
54
+ mysql-als:
55
+ condition: service_healthy
56
+ central-ledger:
57
+ condition: service_healthy
53
58
  healthcheck:
54
59
  test: ["CMD", "sh", "-c" ,"apk --no-cache add curl", ";", "curl", "http://localhost:4001/health"]
55
60
  timeout: 20s
@@ -64,7 +69,8 @@ services:
64
69
  - "-c"
65
70
  - "node src/handlers/index.js h --timeout"
66
71
  depends_on:
67
- - redis-node-0
72
+ account-lookup-service:
73
+ condition: service_healthy
68
74
  ports:
69
75
  - "4003:4003"
70
76
  healthcheck:
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "account-lookup-service",
3
3
  "description": "Account Lookup Service is used to validate Party and Participant lookups.",
4
- "version": "17.1.0",
4
+ "version": "17.2.0",
5
5
  "license": "Apache-2.0",
6
6
  "author": "ModusBox",
7
7
  "contributors": [
@@ -40,6 +40,7 @@
40
40
  "scripts": {
41
41
  "start": "LOG_LEVEL=debug node src/index.js server",
42
42
  "start:all": "run-p start:api start:admin start:handlers",
43
+ "start:apiAndAdmin": "run-p start:api start:admin",
43
44
  "start:api": "node src/index.js server --api",
44
45
  "start:admin": "node src/index.js server --admin",
45
46
  "start:handlers": "node src/handlers/index.js handlers --timeout",
@@ -49,7 +50,7 @@
49
50
  "lint:fix": "npm run standard:fix",
50
51
  "dev": "nodemon src/index.js server",
51
52
  "test": "npm run test:unit",
52
- "test:unit": "NODE_OPTIONS='--experimental-vm-modules' jest --runInBand",
53
+ "test:unit": "NODE_OPTIONS='--experimental-vm-modules --max-old-space-size=8192' jest --runInBand",
53
54
  "test:coverage": "npm test -- --coverage --coverageThreshold='{}'",
54
55
  "test:coverage-check": "npm test -- --coverage",
55
56
  "test:junit": "npm test -- --reporters=default --reporters=jest-junit",
@@ -91,22 +92,22 @@
91
92
  "@hapi/inert": "7.1.0",
92
93
  "@hapi/vision": "7.0.3",
93
94
  "@mojaloop/central-services-error-handling": "13.0.6",
94
- "@mojaloop/central-services-health": "15.0.3",
95
+ "@mojaloop/central-services-health": "15.0.4",
95
96
  "@mojaloop/central-services-logger": "11.5.5",
96
97
  "@mojaloop/central-services-metrics": "12.4.5",
97
- "@mojaloop/central-services-shared": "18.18.0",
98
- "@mojaloop/central-services-stream": "11.4.4",
99
- "@mojaloop/database-lib": "11.1.2",
100
- "@mojaloop/event-sdk": "14.1.3",
101
- "@mojaloop/inter-scheme-proxy-cache-lib": "2.3.1",
102
- "@mojaloop/ml-schema-transformer-lib": "2.5.2",
103
- "@mojaloop/sdk-standard-components": "19.6.4",
98
+ "@mojaloop/central-services-shared": "18.19.0",
99
+ "@mojaloop/central-services-stream": "11.5.1",
100
+ "@mojaloop/database-lib": "11.1.3",
101
+ "@mojaloop/event-sdk": "14.1.5",
102
+ "@mojaloop/inter-scheme-proxy-cache-lib": "2.3.3",
103
+ "@mojaloop/ml-schema-transformer-lib": "2.5.4",
104
+ "@mojaloop/sdk-standard-components": "19.7.0",
104
105
  "@now-ims/hapi-now-auth": "2.1.0",
105
106
  "ajv": "8.17.1",
106
107
  "ajv-keywords": "5.1.0",
107
108
  "blipp": "4.0.2",
108
109
  "commander": "13.1.0",
109
- "cron": "4.0.0",
110
+ "cron": "4.1.0",
110
111
  "fast-safe-stringify": "^2.1.1",
111
112
  "hapi-auth-bearer-token": "8.0.0",
112
113
  "joi": "17.13.3",
@@ -162,7 +163,7 @@
162
163
  "devDependencies": {
163
164
  "@types/jest": "29.5.14",
164
165
  "audit-ci": "^7.1.0",
165
- "axios": "1.7.9",
166
+ "axios": "1.8.1",
166
167
  "axios-retry": "^4.5.0",
167
168
  "docdash": "2.0.2",
168
169
  "dotenv": "^16.4.7",
@@ -172,7 +173,7 @@
172
173
  "jest-junit": "16.0.0",
173
174
  "jsdoc": "4.0.4",
174
175
  "nodemon": "3.1.9",
175
- "npm-check-updates": "17.1.14",
176
+ "npm-check-updates": "17.1.15",
176
177
  "nyc": "17.1.0",
177
178
  "pre-commit": "1.2.2",
178
179
  "proxyquire": "2.1.3",
@@ -12,7 +12,9 @@ const expectedContainers = [
12
12
  'als_mysql',
13
13
  'als_kafka',
14
14
  'als_mysql_central_ledger',
15
- 'als_central-ledger'
15
+ 'als_central-ledger',
16
+ 'als_account-lookup-service',
17
+ 'als_account-lookup-service-handlers'
16
18
  // ## NOTE: These are not needed for Integration Tests
17
19
  // 'kowl'
18
20
  ]
@@ -35,6 +35,7 @@ const cachedOracleEndpoint = require('../../models/oracle/oracleEndpointCached')
35
35
  const partyIdType = require('../../models/partyIdType')
36
36
  const endpointType = require('../../models/endpointType')
37
37
  const currency = require('../../models/currency')
38
+ const util = require('../../lib/util')
38
39
 
39
40
  /**
40
41
  * @function createOracle
@@ -49,7 +50,6 @@ exports.createOracle = async (payload) => {
49
50
  'Create Oracle',
50
51
  ['success']
51
52
  ).startTimer()
52
- const errorCounter = Metrics.getCounter('errorCount')
53
53
  let step
54
54
 
55
55
  try {
@@ -91,15 +91,7 @@ exports.createOracle = async (payload) => {
91
91
  histTimerEnd({ success: false })
92
92
  Logger.isErrorEnabled && Logger.error(err)
93
93
  const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
94
- const extensions = err.extensions || []
95
- const system = extensions.find((element) => element.key === 'system')?.value || ''
96
- errorCounter.inc({
97
- code: fspiopError?.apiErrorCode?.code,
98
- system,
99
- operation: 'createOracle',
100
- step
101
- })
102
- throw fspiopError
94
+ util.rethrowAndCountFspiopError(fspiopError, { operation: 'createOracle', step })
103
95
  }
104
96
  }
105
97
 
@@ -116,7 +108,6 @@ exports.getOracle = async (query) => {
116
108
  'Get Oracle',
117
109
  ['success']
118
110
  ).startTimer()
119
- const errorCounter = Metrics.getCounter('errorCount')
120
111
  let step
121
112
  try {
122
113
  let oracleEndpointModelList
@@ -160,15 +151,7 @@ exports.getOracle = async (query) => {
160
151
  histTimerEnd({ success: false })
161
152
  Logger.isErrorEnabled && Logger.error(err)
162
153
  const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
163
- const extensions = err.extensions || []
164
- const system = extensions.find((element) => element.key === 'system')?.value || ''
165
- errorCounter.inc({
166
- code: fspiopError?.apiErrorCode?.code,
167
- system,
168
- operation: 'getOracle',
169
- step
170
- })
171
- throw fspiopError
154
+ util.rethrowAndCountFspiopError(fspiopError, { operation: 'getOracle', step })
172
155
  }
173
156
  }
174
157
 
@@ -186,7 +169,6 @@ exports.updateOracle = async (params, payload) => {
186
169
  'Update Oracle',
187
170
  ['success']
188
171
  ).startTimer()
189
- const errorCounter = Metrics.getCounter('errorCount')
190
172
  let step
191
173
  try {
192
174
  step = 'getOracleEndpointById-1'
@@ -247,15 +229,7 @@ exports.updateOracle = async (params, payload) => {
247
229
  histTimerEnd({ success: false })
248
230
  Logger.isErrorEnabled && Logger.error(err)
249
231
  const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
250
- const extensions = err.extensions || []
251
- const system = extensions.find((element) => element.key === 'system')?.value || ''
252
- errorCounter.inc({
253
- code: fspiopError?.apiErrorCode?.code,
254
- system,
255
- operation: 'updateOracle',
256
- step
257
- })
258
- throw fspiopError
232
+ util.rethrowAndCountFspiopError(fspiopError, { operation: 'updateOracle', step })
259
233
  }
260
234
  }
261
235
 
@@ -272,7 +246,6 @@ exports.deleteOracle = async (params) => {
272
246
  'Delete Oracle',
273
247
  ['success']
274
248
  ).startTimer()
275
- const errorCounter = Metrics.getCounter('errorCount')
276
249
  try {
277
250
  await oracleEndpoint.destroyOracleEndpointById(params.ID)
278
251
  histTimerEnd({ success: true })
@@ -281,13 +254,6 @@ exports.deleteOracle = async (params) => {
281
254
  histTimerEnd({ success: false })
282
255
  Logger.isErrorEnabled && Logger.error(err)
283
256
  const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
284
- const extensions = err.extensions || []
285
- const system = extensions.find((element) => element.key === 'system')?.value || ''
286
- errorCounter.inc({
287
- code: fspiopError?.apiErrorCode?.code,
288
- system,
289
- operation: 'deleteOracle'
290
- })
291
- throw fspiopError
257
+ util.rethrowAndCountFspiopError(fspiopError, { operation: 'deleteOracle' })
292
258
  }
293
259
  }
@@ -37,6 +37,7 @@ const participant = require('../../models/participantEndpoint/facade')
37
37
  const Config = require('../../lib/config')
38
38
  const { logger } = require('../../lib')
39
39
  const { ERROR_MESSAGES } = require('../../constants')
40
+ const util = require('../../lib/util')
40
41
 
41
42
  const { FSPIOPErrorCodes } = ErrorHandler.Enums
42
43
 
@@ -58,7 +59,6 @@ const getParticipantsByTypeAndID = async (headers, params, method, query, span,
58
59
  'Get participants by ID',
59
60
  ['success']
60
61
  ).startTimer()
61
- const errorCounter = Metrics.getCounter('errorCount')
62
62
  const log = logger.child('getParticipantsByTypeAndID')
63
63
  const type = params.Type
64
64
  const partySubIdOrType = params.SubId
@@ -128,14 +128,9 @@ const getParticipantsByTypeAndID = async (headers, params, method, query, span,
128
128
  } catch (err) {
129
129
  log.warn('error in getParticipantsByTypeAndID', err)
130
130
  fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
131
- const extensions = err.extensions || []
132
- const system = extensions.find((element) => element.key === 'system')?.value || ''
133
- errorCounter.inc({
134
- code: fspiopError?.apiErrorCode?.code,
135
- system,
136
- operation: 'getParticipantsByTypeAndID',
137
- step
138
- })
131
+ if (fspiopError) {
132
+ util.countFspiopError(fspiopError, { operation: 'getParticipantsByTypeAndID', step })
133
+ }
139
134
  try {
140
135
  await participant.sendErrorToParticipant(
141
136
  headers[Enums.Http.Headers.FSPIOP.SOURCE],
@@ -180,7 +175,6 @@ const putParticipantsByTypeAndID = async (headers, params, method, payload, cach
180
175
  'Put participants by type and ID',
181
176
  ['success']
182
177
  ).startTimer()
183
- const errorCounter = Metrics.getCounter('errorCount')
184
178
  let step
185
179
  try {
186
180
  logger.info('putParticipantsByTypeAndID::begin')
@@ -249,14 +243,9 @@ const putParticipantsByTypeAndID = async (headers, params, method, payload, cach
249
243
  // we've already sent a sync response- we cannot throw.
250
244
  logger.error('error in participant.sendErrorToParticipant:', exc)
251
245
  }
252
- const extensions = err.extensions || []
253
- const system = extensions.find((element) => element.key === 'system')?.value || ''
254
- errorCounter.inc({
255
- code: fspiopError?.apiErrorCode?.code,
256
- system,
257
- operation: 'putParticipantsByTypeAndID',
258
- step
259
- })
246
+ if (fspiopError) {
247
+ util.countFspiopError(fspiopError, { operation: 'putParticipantsByTypeAndID', step })
248
+ }
260
249
  histTimerEnd({ success: false })
261
250
  }
262
251
  }
@@ -280,7 +269,6 @@ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri
280
269
  'Put participants error by type and ID',
281
270
  ['success']
282
271
  ).startTimer()
283
- const errorCounter = Metrics.getCounter('errorCount')
284
272
  let step
285
273
  try {
286
274
  const partySubIdOrType = params.SubId || undefined
@@ -325,14 +313,7 @@ const putParticipantsErrorByTypeAndID = async (headers, params, payload, dataUri
325
313
  headers,
326
314
  params
327
315
  )
328
- const extensions = err.extensions || []
329
- const system = extensions.find((element) => element.key === 'system')?.value || ''
330
- errorCounter.inc({
331
- code: fspiopError?.apiErrorCode?.code,
332
- system,
333
- operation: 'putParticipantsErrorByTypeAndID',
334
- step
335
- })
316
+ util.countFspiopError(fspiopError, { operation: 'putParticipantsErrorByTypeAndID', step })
336
317
  } catch (exc) {
337
318
  // We can't do anything else here- we _must_ handle all errors _within_ this function because
338
319
  // we've already sent a sync response- we cannot throw.
@@ -359,7 +340,6 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
359
340
  'Post participants',
360
341
  ['success']
361
342
  ).startTimer()
362
- const errorCounter = Metrics.getCounter('errorCount')
363
343
  const childSpan = span ? span.getChild('postParticipants') : undefined
364
344
  let fspiopError
365
345
  let step
@@ -431,14 +411,9 @@ const postParticipants = async (headers, method, params, payload, span, cache) =
431
411
  } catch (err) {
432
412
  logger.error('error in postParticipants:', err)
433
413
  fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err, ErrorHandler.Enums.FSPIOPErrorCodes.ADD_PARTY_INFO_ERROR)
434
- const extensions = err.extensions || []
435
- const system = extensions.find((element) => element.key === 'system')?.value || ''
436
- errorCounter.inc({
437
- code: fspiopError?.apiErrorCode?.code,
438
- system,
439
- operation: 'postParticipants',
440
- step
441
- })
414
+ if (fspiopError) {
415
+ util.countFspiopError(fspiopError, { operation: 'postParticipants', step })
416
+ }
442
417
  try {
443
418
  const errorCallbackEndpointType = params.SubId
444
419
  ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR
@@ -476,7 +451,6 @@ const postParticipantsBatch = async (headers, method, requestPayload, span) => {
476
451
  'Post participants batch',
477
452
  ['success']
478
453
  ).startTimer()
479
- const errorCounter = Metrics.getCounter('errorCount')
480
454
  const requestId = requestPayload.requestId
481
455
  const log = logger.child({ context: 'postParticipantsBatch', requestId })
482
456
  const childSpan = span ? span.getChild('postParticipantsBatch') : undefined
@@ -563,14 +537,9 @@ const postParticipantsBatch = async (headers, method, requestPayload, span) => {
563
537
  } catch (err) {
564
538
  log.error('error in postParticipantsBatch', err)
565
539
  fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
566
- const extensions = err.extensions || []
567
- const system = extensions.find((element) => element.key === 'system')?.value || ''
568
- errorCounter.inc({
569
- code: fspiopError?.apiErrorCode?.code,
570
- system,
571
- operation: 'postParticipantsBatch',
572
- step
573
- })
540
+ if (fspiopError) {
541
+ util.countFspiopError(fspiopError, { operation: 'postParticipantsBatch', step })
542
+ }
574
543
  try {
575
544
  await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_BATCH_PUT_ERROR,
576
545
  fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, undefined, requestPayload)
@@ -606,7 +575,6 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
606
575
  'Delete participants',
607
576
  ['success']
608
577
  ).startTimer()
609
- const errorCounter = Metrics.getCounter('errorCount')
610
578
  const log = logger.child('deleteParticipants')
611
579
  let step
612
580
  try {
@@ -659,14 +627,7 @@ const deleteParticipants = async (headers, params, method, query, cache) => {
659
627
  const errorCallbackEndpointType = params.SubId ? Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_SUB_ID_PUT_ERROR : Enums.EndPoints.FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTICIPANT_PUT_ERROR
660
628
  await participant.sendErrorToParticipant(headers[Enums.Http.Headers.FSPIOP.SOURCE], errorCallbackEndpointType,
661
629
  fspiopError.toApiErrorObject(Config.ERROR_HANDLING), headers, params)
662
- const extensions = err.extensions || []
663
- const system = extensions.find((element) => element.key === 'system')?.value || ''
664
- errorCounter.inc({
665
- code: fspiopError?.apiErrorCode?.code,
666
- system,
667
- operation: 'deleteParticipants',
668
- step
669
- })
630
+ util.countFspiopError(fspiopError, { operation: 'deleteParticipants', step })
670
631
  } catch (exc) {
671
632
  // We can't do anything else here- we _must_ handle all errors _within_ this function because
672
633
  // we've already sent a sync response- we cannot throw.
@@ -35,6 +35,7 @@ const { ERROR_MESSAGES } = require('../../constants')
35
35
  const { logger } = require('../../lib')
36
36
  const Config = require('../../lib/config')
37
37
  const utils = require('./utils')
38
+ const util = require('../../lib/util')
38
39
 
39
40
  const { FspEndpointTypes, FspEndpointTemplates } = Enum.EndPoints
40
41
  const { Headers, RestMethods } = Enum.Http
@@ -87,7 +88,6 @@ const getPartiesByTypeAndID = async (headers, params, method, query, span, cache
87
88
  'Get party by Type and Id',
88
89
  ['success']
89
90
  ).startTimer()
90
- const errorCounter = Metrics.getCounter('errorCount')
91
91
  const proxyEnabled = !!(Config.PROXY_CACHE_CONFIG.enabled && proxyCache)
92
92
  const type = params.Type
93
93
  const partySubId = params.SubId
@@ -245,14 +245,9 @@ const getPartiesByTypeAndID = async (headers, params, method, query, span, cache
245
245
  } catch (err) {
246
246
  fspiopError = await handleErrorOnSendingCallback(err, headers, params, requester)
247
247
  histTimerEnd({ success: false })
248
- const extensions = err.extensions || []
249
- const system = extensions.find((element) => element.key === 'system')?.value || ''
250
- errorCounter.inc({
251
- code: fspiopError?.apiErrorCode?.code,
252
- system,
253
- operation: 'getPartiesByTypeAndID',
254
- step
255
- })
248
+ if (fspiopError) {
249
+ util.countFspiopError(fspiopError, { operation: 'getPartiesByTypeAndID', step })
250
+ }
256
251
  } finally {
257
252
  await utils.finishSpanWithError(childSpan, fspiopError)
258
253
  }
@@ -41,6 +41,7 @@ const { ERROR_MESSAGES } = require('../../constants')
41
41
  const { logger } = require('../../lib')
42
42
  const Config = require('../../lib/config')
43
43
  const utils = require('./utils')
44
+ const util = require('../../lib/util')
44
45
  const getPartiesByTypeAndID = require('./getPartiesByTypeAndID')
45
46
 
46
47
  const log = logger.child('domain:put-parties')
@@ -65,7 +66,6 @@ const putPartiesByTypeAndID = async (headers, params, method, payload, dataUri,
65
66
  'Put parties by type and id',
66
67
  ['success']
67
68
  ).startTimer()
68
- const errorCounter = Metrics.getCounter('errorCount')
69
69
  const type = params.Type
70
70
  const partySubId = params.SubId
71
71
  const source = headers[Headers.FSPIOP.SOURCE]
@@ -134,14 +134,9 @@ const putPartiesByTypeAndID = async (headers, params, method, payload, dataUri,
134
134
  histTimerEnd({ success: true })
135
135
  } catch (err) {
136
136
  const fspiopError = await handleErrorOnSendingCallback(err, headers, params, sendTo)
137
- const extensions = err.extensions || []
138
- const system = extensions.find((element) => element.key === 'system')?.value || ''
139
- errorCounter.inc({
140
- code: fspiopError?.apiErrorCode?.code,
141
- system,
142
- operation: 'putPartiesByTypeAndID',
143
- step
144
- })
137
+ if (fspiopError) {
138
+ util.countFspiopError(fspiopError, { operation: 'putPartiesByTypeAndID', step })
139
+ }
145
140
  histTimerEnd({ success: false })
146
141
  }
147
142
  }
@@ -165,7 +160,6 @@ const putPartiesErrorByTypeAndID = async (headers, params, payload, dataUri, spa
165
160
  'Put parties error by type and id',
166
161
  ['success']
167
162
  ).startTimer()
168
- const errorCounter = Metrics.getCounter('errorCount')
169
163
  const partySubId = params.SubId
170
164
  const destination = headers[Headers.FSPIOP.DESTINATION]
171
165
  const callbackEndpointType = utils.errorPartyCbType(partySubId)
@@ -220,14 +214,9 @@ const putPartiesErrorByTypeAndID = async (headers, params, payload, dataUri, spa
220
214
  histTimerEnd({ success: true })
221
215
  } catch (err) {
222
216
  fspiopError = await handleErrorOnSendingCallback(err, headers, params, sendTo)
223
- const extensions = err.extensions || []
224
- const system = extensions.find((element) => element.key === 'system')?.value || ''
225
- errorCounter.inc({
226
- code: fspiopError?.apiErrorCode?.code,
227
- system,
228
- operation: 'putPartiesErrorByTypeAndID',
229
- step
230
- })
217
+ if (fspiopError) {
218
+ util.countFspiopError(fspiopError, { operation: 'putPartiesErrorByTypeAndID', step })
219
+ }
231
220
  histTimerEnd({ success: false })
232
221
  } finally {
233
222
  await utils.finishSpanWithError(childSpan, fspiopError)
@@ -46,6 +46,7 @@ const Participant = require('../../models/participantEndpoint/facade')
46
46
  const { ERROR_MESSAGES } = require('../../constants')
47
47
  const { timeoutCallbackDto } = require('./dto')
48
48
  const { logger } = require('../../lib')
49
+ const util = require('../../lib/util')
49
50
 
50
51
  const timeoutInterschemePartiesLookups = async ({ proxyCache, batchSize }) => {
51
52
  return proxyCache.processExpiredAlsKeys(sendTimeoutCallback, batchSize)
@@ -57,7 +58,6 @@ const sendTimeoutCallback = async (cacheKey) => {
57
58
  'Egress - Interscheme parties lookup timeout callback',
58
59
  ['success']
59
60
  ).startTimer()
60
- const errorCounter = Metrics.getCounter('errorCount')
61
61
  let step
62
62
  const [, destination, partyType, partyId] = cacheKey.split(':')
63
63
  const { errorInformation, params, headers, endpointType, span } = await timeoutCallbackDto({ destination, partyId, partyType })
@@ -74,14 +74,8 @@ const sendTimeoutCallback = async (cacheKey) => {
74
74
  logger.warn('error in sendTimeoutCallback: ', err)
75
75
  histTimerEnd({ success: false })
76
76
  const fspiopError = reformatFSPIOPError(err)
77
- const extensions = err.extensions || []
78
- const system = extensions.find((element) => element.key === 'system')?.value || ''
79
- errorCounter.inc({
80
- code: fspiopError?.apiErrorCode?.code,
81
- system,
82
- operation: 'sendTimeoutCallback',
83
- step
84
- })
77
+ util.countFspiopError(fspiopError, { operation: 'sendTimeoutCallback', step })
78
+
85
79
  await finishSpan(span, fspiopError)
86
80
  throw fspiopError
87
81
  }
package/src/lib/util.js CHANGED
@@ -1,8 +1,9 @@
1
1
  const util = require('util')
2
2
  const Path = require('path')
3
3
  const Enum = require('@mojaloop/central-services-shared').Enum
4
- const { HeaderValidation, Hapi } = require('@mojaloop/central-services-shared').Util
4
+ const { HeaderValidation, Hapi, rethrow } = require('@mojaloop/central-services-shared').Util
5
5
  const Config = require('../lib/config')
6
+ const { logger } = require('./index')
6
7
 
7
8
  const getSpanTags = ({ headers }, transactionType, transactionAction) => {
8
9
  const tags = {
@@ -55,6 +56,20 @@ function getStackOrInspect (err) {
55
56
  return err?.stack || util.inspect(err)
56
57
  }
57
58
 
59
+ const rethrowAndCountFspiopError = (error, options) => {
60
+ options.loggerOverride = logger
61
+ rethrow.rethrowAndCountFspiopError(error, options)
62
+ }
63
+
64
+ const rethrowDatabaseError = (error) => {
65
+ rethrow.rethrowDatabaseError(error, { loggerOverride: logger })
66
+ }
67
+
68
+ const countFspiopError = (error, options) => {
69
+ options.loggerOverride = logger
70
+ rethrow.countFspiopError(error, options)
71
+ }
72
+
58
73
  module.exports = {
59
74
  getSpanTags,
60
75
  pathForInterface,
@@ -62,5 +77,8 @@ module.exports = {
62
77
  hubNameConfig: {
63
78
  hubName: Config.HUB_NAME,
64
79
  hubNameRegex: HeaderValidation.getHubNameRegex(Config.HUB_NAME)
65
- }
80
+ },
81
+ rethrowAndCountFspiopError,
82
+ rethrowDatabaseError,
83
+ countFspiopError
66
84
  }
@@ -26,7 +26,7 @@
26
26
  'use strict'
27
27
 
28
28
  const Db = require('../../lib/db')
29
- const ErrorHandler = require('@mojaloop/central-services-error-handling')
29
+ const util = require('../../lib/util')
30
30
 
31
31
  /**
32
32
  * @function getCurrencyById
@@ -39,16 +39,7 @@ const getCurrencyById = async (currencyId) => {
39
39
  try {
40
40
  return Db.from('currency').findOne({ currencyId, isActive: true })
41
41
  } catch (err) {
42
- const extensions = [{
43
- key: 'system',
44
- value: '["db"]'
45
- }]
46
- throw ErrorHandler.Factory.reformatFSPIOPError(
47
- err,
48
- undefined,
49
- undefined,
50
- extensions
51
- )
42
+ util.rethrowDatabaseError(err)
52
43
  }
53
44
  }
54
45
 
@@ -26,7 +26,7 @@
26
26
  'use strict'
27
27
 
28
28
  const Db = require('../../lib/db')
29
- const ErrorHandler = require('@mojaloop/central-services-error-handling')
29
+ const util = require('../../lib/util')
30
30
 
31
31
  /**
32
32
  * @function getEndpointTypeByType
@@ -39,16 +39,7 @@ const getEndpointTypeByType = async (type) => {
39
39
  try {
40
40
  return Db.from('endpointType').findOne({ type, isActive: true })
41
41
  } catch (err) {
42
- const extensions = [{
43
- key: 'system',
44
- value: '["db"]'
45
- }]
46
- throw ErrorHandler.Factory.reformatFSPIOPError(
47
- err,
48
- undefined,
49
- undefined,
50
- extensions
51
- )
42
+ util.rethrowDatabaseError(err)
52
43
  }
53
44
  }
54
45
 
@@ -26,11 +26,7 @@
26
26
  'use strict'
27
27
 
28
28
  const Db = require('../../lib/db')
29
- const ErrorHandler = require('@mojaloop/central-services-error-handling')
30
- const extensions = [{
31
- key: 'system',
32
- value: '["db"]'
33
- }]
29
+ const util = require('../../lib/util')
34
30
 
35
31
  const getOracleEndpointByType = async (type) => {
36
32
  try {
@@ -47,12 +43,7 @@ const getOracleEndpointByType = async (type) => {
47
43
  'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
48
44
  })
49
45
  } catch (err) {
50
- throw ErrorHandler.Factory.reformatFSPIOPError(
51
- err,
52
- undefined,
53
- undefined,
54
- extensions
55
- )
46
+ util.rethrowDatabaseError(err)
56
47
  }
57
48
  }
58
49
 
@@ -73,12 +64,7 @@ const getOracleEndpointByTypeAndCurrency = async (type, currencyId) => {
73
64
  'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
74
65
  })
75
66
  } catch (err) {
76
- throw ErrorHandler.Factory.reformatFSPIOPError(
77
- err,
78
- undefined,
79
- undefined,
80
- extensions
81
- )
67
+ util.rethrowDatabaseError(err)
82
68
  }
83
69
  }
84
70
 
@@ -98,12 +84,7 @@ const getOracleEndpointByCurrency = async (currencyId) => {
98
84
  'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
99
85
  })
100
86
  } catch (err) {
101
- throw ErrorHandler.Factory.reformatFSPIOPError(
102
- err,
103
- undefined,
104
- undefined,
105
- extensions
106
- )
87
+ util.rethrowDatabaseError(err)
107
88
  }
108
89
  }
109
90
 
@@ -123,12 +104,7 @@ const getOracleEndpointById = async (oracleEndpointId) => {
123
104
  'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
124
105
  })
125
106
  } catch (err) {
126
- throw ErrorHandler.Factory.reformatFSPIOPError(
127
- err,
128
- undefined,
129
- undefined,
130
- extensions
131
- )
107
+ util.rethrowDatabaseError(err)
132
108
  }
133
109
  }
134
110
 
@@ -146,12 +122,7 @@ const getAllOracleEndpoint = async () => {
146
122
  'pt.name as idType', 'oracleEndpoint.currencyId as currency', 'oracleEndpoint.isDefault')
147
123
  })
148
124
  } catch (err) {
149
- throw ErrorHandler.Factory.reformatFSPIOPError(
150
- err,
151
- undefined,
152
- undefined,
153
- extensions
154
- )
125
+ util.rethrowDatabaseError(err)
155
126
  }
156
127
  }
157
128
 
@@ -161,7 +132,7 @@ const getAllOracleEndpointsByMatchCondition = async (oracleEndpointModel, partyI
161
132
  return builder.innerJoin('endpointType AS et', 'oracleEndpoint.endpointTypeId', 'et.endpointTypeId')
162
133
  .innerJoin('partyIdType AS pt', 'oracleEndpoint.partyIdTypeId', 'pt.partyIdTypeId')
163
134
  .where({
164
- 'oracleEndpoint.currencyId': oracleEndpointModel.currency,
135
+ 'oracleEndpoint.currencyId': oracleEndpointModel?.currency || null,
165
136
  'et.endpointTypeId': endpointTypeId,
166
137
  'pt.partyIdTypeId': partyIdTypeId,
167
138
  'oracleEndpoint.isActive': 1
@@ -171,12 +142,7 @@ const getAllOracleEndpointsByMatchCondition = async (oracleEndpointModel, partyI
171
142
  'oracleEndpoint.isActive', 'oracleEndpoint.partyIdTypeId', 'oracleEndpoint.endpointTypeId', 'oracleEndpoint.currencyId')
172
143
  })
173
144
  } catch (err) {
174
- throw ErrorHandler.Factory.reformatFSPIOPError(
175
- err,
176
- undefined,
177
- undefined,
178
- extensions
179
- )
145
+ util.rethrowDatabaseError(err)
180
146
  }
181
147
  }
182
148
 
@@ -184,12 +150,7 @@ const createOracleEndpoint = async (oracleEndpointModel) => {
184
150
  try {
185
151
  return await Db.from('oracleEndpoint').insert(oracleEndpointModel)
186
152
  } catch (err) {
187
- throw ErrorHandler.Factory.reformatFSPIOPError(
188
- err,
189
- undefined,
190
- undefined,
191
- extensions
192
- )
153
+ util.rethrowDatabaseError(err)
193
154
  }
194
155
  }
195
156
 
@@ -197,12 +158,7 @@ const updateOracleEndpointById = async (id, oracleEndpointModel) => {
197
158
  try {
198
159
  return await Db.from('oracleEndpoint').update({ oracleEndpointId: id }, oracleEndpointModel)
199
160
  } catch (err) {
200
- throw ErrorHandler.Factory.reformatFSPIOPError(
201
- err,
202
- undefined,
203
- undefined,
204
- extensions
205
- )
161
+ util.rethrowDatabaseError(err)
206
162
  }
207
163
  }
208
164
 
@@ -210,12 +166,7 @@ const setIsActiveOracleEndpoint = async (oracleType, isActive) => {
210
166
  try {
211
167
  return await Db.from('oracleEndpoint').update({ oracleType }, { isActive })
212
168
  } catch (err) {
213
- throw ErrorHandler.Factory.reformatFSPIOPError(
214
- err,
215
- undefined,
216
- undefined,
217
- extensions
218
- )
169
+ util.rethrowDatabaseError(err)
219
170
  }
220
171
  }
221
172
 
@@ -223,12 +174,7 @@ const destroyOracleEndpointById = async (oracleEndpointId) => {
223
174
  try {
224
175
  return await Db.from('oracleEndpoint').update({ oracleEndpointId }, { isActive: false })
225
176
  } catch (err) {
226
- throw ErrorHandler.Factory.reformatFSPIOPError(
227
- err,
228
- undefined,
229
- undefined,
230
- extensions
231
- )
177
+ util.rethrowDatabaseError(err)
232
178
  }
233
179
  }
234
180
 
@@ -26,22 +26,13 @@
26
26
  'use strict'
27
27
 
28
28
  const Db = require('../../lib/db')
29
- const ErrorHandler = require('@mojaloop/central-services-error-handling')
29
+ const util = require('../../lib/util')
30
30
 
31
31
  const getPartyIdTypeByName = async (name) => {
32
32
  try {
33
33
  return Db.from('partyIdType').findOne({ name, isActive: true })
34
34
  } catch (err) {
35
- const extensions = [{
36
- key: 'system',
37
- value: '["db"]'
38
- }]
39
- throw ErrorHandler.Factory.reformatFSPIOPError(
40
- err,
41
- undefined,
42
- undefined,
43
- extensions
44
- )
35
+ util.rethrowDatabaseError(err)
45
36
  }
46
37
  }
47
38
 
package/src/server.js CHANGED
@@ -106,13 +106,6 @@ const createServer = async (port, api, routes, isAdmin, proxyCacheConfig, proxyM
106
106
 
107
107
  server.route(routes)
108
108
 
109
- // Initialize the error count metric
110
- Metrics.getCounter(
111
- 'errorCount',
112
- 'Error count',
113
- ['code', 'system', 'operation', 'step']
114
- )
115
-
116
109
  // TODO: follow instructions https://github.com/anttiviljami/openapi-backend/blob/master/DOCS.md#postresponsehandler-handler
117
110
  await server.start()
118
111
 
@@ -174,7 +167,10 @@ const initializeAdmin = async (appConfig) => {
174
167
  RUN_MIGRATIONS && await migrate()
175
168
  const OpenAPISpecPath = Util.pathForInterface({ isAdmin: true, isMockInterface: false })
176
169
  const api = await OpenapiBackend.initialise(OpenAPISpecPath, APIHandlers.AdminHandlers)
177
-
170
+ await Promise.all([
171
+ OracleEndpointCache.initialize(),
172
+ Cache.initCache()
173
+ ])
178
174
  return createServer(ADMIN_PORT, api, Routes.AdminRoutes(api), true, PROXY_CACHE_CONFIG)
179
175
  }
180
176
 
@@ -82,6 +82,15 @@ describe('Oracle', () => {
82
82
  }
83
83
  }
84
84
 
85
+ const oracleUsdMsisdnNoCurrencyUrlPayload = {
86
+ isDefault: true,
87
+ oracleIdType: 'MSISDN',
88
+ endpoint: {
89
+ value: 'http://localhost:8444',
90
+ endpointType: 'URL'
91
+ }
92
+ }
93
+
85
94
  describe('Create', () => {
86
95
  it('creates an oracle', async () => {
87
96
  const result = await Oracle.createOracle(oracleAuhMsisdnUrlPayload, createHeaders, testSpan)
@@ -126,6 +135,15 @@ describe('Oracle', () => {
126
135
  const createdId = oracleEndpointResult[0].oracleEndpointId
127
136
  await Db.from('oracleEndpoint').destroy({ oracleEndpointId: createdId })
128
137
  })
138
+
139
+ it('creates an oracle without a currency', async () => {
140
+ const result = await Oracle.createOracle(oracleUsdMsisdnNoCurrencyUrlPayload, createHeaders, testSpan)
141
+ expect(result).toBe(true)
142
+
143
+ const oracleEndpointResult = await OracleModel.getOracleEndpointByType('MSISDN')
144
+ const createdId = oracleEndpointResult[0].oracleEndpointId
145
+ await Db.from('oracleEndpoint').destroy({ oracleEndpointId: createdId })
146
+ })
129
147
  })
130
148
 
131
149
  describe('Update', () => {
@@ -6,7 +6,7 @@ const config = require('../../../../src/lib/config')
6
6
 
7
7
  const wait = (sec) => new Promise(resolve => setTimeout(resolve, sec * 1000))
8
8
 
9
- const CRON_TIMEOUT_SEC = 10 // see TIMEXP
9
+ const CRON_TIMEOUT_SEC = 15 // see TIMEXP
10
10
 
11
11
  describe('Timeout Handler', () => {
12
12
  const { type, proxyConfig } = config.PROXY_CACHE_CONFIG
@@ -1369,7 +1369,7 @@ describe('participant Tests', () => {
1369
1369
 
1370
1370
  // Assert
1371
1371
  expect(logStub.getCall(0).firstArg).toBe(ERROR_MESSAGES.sourceFspNotFound)
1372
- expect(logStub.getCall(2).lastArg).toEqual(cbError)
1372
+ expect(logStub.getCall(3).lastArg).toEqual(cbError)
1373
1373
  })
1374
1374
 
1375
1375
  it('handles error when `oracleBatchRequest` returns no result', async () => {
@@ -246,7 +246,7 @@ describe('Parties Tests', () => {
246
246
  await partiesDomain.getPartiesByTypeAndID(Helper.getByTypeIdRequest.headers, Helper.getByTypeIdRequest.params, Helper.getByTypeIdRequest.method, Helper.getByTypeIdRequest.query)
247
247
 
248
248
  // Assert
249
- expect(loggerStub.callCount).toBe(1)
249
+ expect(loggerStub.callCount).toBe(2)
250
250
  expect(participant.sendErrorToParticipant.callCount).toBe(1)
251
251
 
252
252
  const { errorInformation } = participant.sendErrorToParticipant.getCall(0).args[2]
@@ -893,7 +893,7 @@ describe('Parties Tests', () => {
893
893
 
894
894
  // Assert
895
895
  expect(participant.sendErrorToParticipant.callCount).toBe(1)
896
- expect(loggerStub.callCount).toBe(1)
896
+ expect(loggerStub.callCount).toBe(2)
897
897
  const sendErrorCallArgs = participant.sendErrorToParticipant.getCall(0).args
898
898
  expect(sendErrorCallArgs[1]).toBe(expectedCallbackEnpointType)
899
899
  })
@@ -914,7 +914,7 @@ describe('Parties Tests', () => {
914
914
 
915
915
  // Assert
916
916
  expect(participant.sendErrorToParticipant.callCount).toBe(1)
917
- expect(loggerStub.callCount).toBe(1)
917
+ expect(loggerStub.callCount).toBe(2)
918
918
  const sendErrorCallArgs = participant.sendErrorToParticipant.getCall(0).args
919
919
  expect(sendErrorCallArgs[1]).toBe(expectedCallbackEnpointType)
920
920
  })