account-lookup-service 17.8.0-snapshot.7 → 17.8.0-snapshot.8

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/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.8.0-snapshot.7",
4
+ "version": "17.8.0-snapshot.8",
5
5
  "license": "Apache-2.0",
6
6
  "author": "ModusBox",
7
7
  "contributors": [
@@ -46,12 +46,10 @@ class GetPartiesService extends BasePartiesService {
46
46
  }
47
47
 
48
48
  const response = await this.sendOracleDiscoveryRequest()
49
- if (Array.isArray(response?.data?.partyList) && response.data.partyList.length > 0) {
50
- const isDone = await this.processOraclePartyListResponse(response)
51
- if (isDone) return
52
- }
49
+ const isSent = await this.processOraclePartyListResponse(response)
50
+ this.log.info(`getParties request is ${isSent ? '' : 'NOT '}forwarded to oracle lookup DFSP`)
51
+ if (isSent) return
53
52
 
54
- this.log.info('no forwarded requests for oracle partyList')
55
53
  const fspiopError = await this.triggerInterSchemeDiscoveryFlow(this.inputs.headers)
56
54
  if (fspiopError) {
57
55
  this.state.fspiopError = fspiopError // todo: think, if we need this
@@ -118,6 +116,11 @@ class GetPartiesService extends BasePartiesService {
118
116
  }
119
117
 
120
118
  async processOraclePartyListResponse (response) {
119
+ if (!Array.isArray(response?.data?.partyList) || response.data.partyList.length === 0) {
120
+ this.log.verbose('oracle partyList is empty')
121
+ return false
122
+ }
123
+
121
124
  this.stepInProgress('processOraclePartyList')
122
125
  const partyList = this.#filterOraclePartyList(response)
123
126
 
@@ -127,48 +130,31 @@ class GetPartiesService extends BasePartiesService {
127
130
  if (isSent) sentCount++
128
131
  }))
129
132
 
130
- const isDone = sentCount > 0
131
- this.log.verbose('processOraclePartyList is done', { isDone, sentCount })
132
- // if NOT isDone, need to trigger interScheme discovery flow
133
- return isDone
133
+ const isSent = sentCount > 0
134
+ this.log.verbose('processOraclePartyList is done', { isSent, sentCount })
135
+ // if NOT isSent, need to trigger interScheme discovery flow
136
+ return isSent
134
137
  }
135
138
 
136
139
  async triggerInterSchemeDiscoveryFlow (headers) {
137
140
  const { params } = this.inputs
138
141
  const { proxy, source } = this.state
139
- const log = this.log.child({ method: 'triggerInterSchemeDiscoveryFlow' })
140
- log.verbose('triggerInterSchemeDiscoveryFlow start...', { proxy, source })
142
+ const log = this.log.child({ source })
143
+ log.verbose('triggerInterSchemeDiscoveryFlow start...', { proxy })
141
144
 
142
145
  const proxyNames = await this.#getFilteredProxyList(proxy)
143
146
  if (!proxyNames.length) {
144
147
  return this.#sendPartyNotFoundErrorCallback(headers)
145
148
  }
146
149
 
147
- this.stepInProgress('setSendToProxiesList-10')
148
- const alsReq = this.deps.partiesUtils.alsRequestDto(source, params)
149
- log.verbose('starting setSendToProxiesList flow: ', { proxyNames, alsReq, proxyCacheTtlSec })
150
-
151
- const isCached = await this.deps.proxyCache.setSendToProxiesList(alsReq, proxyNames, proxyCacheTtlSec)
152
- if (!isCached) {
153
- throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.failedToCacheSendToProxiesList, log)
154
- }
155
-
156
- this.stepInProgress('sendingProxyRequests')
157
- const sending = proxyNames.map(
158
- sendTo => this.#forwardGetPartiesRequest({ sendTo, headers, params })
159
- .then(({ status, data } = {}) => ({ status, data }))
160
- )
161
- const results = await Promise.allSettled(sending)
162
- const isOk = results.some(result => result.status === 'fulfilled')
163
- // If, at least, one request is sent to proxy, we treat the whole flow as successful.
164
- // Failed requests should be handled by TTL expired/timeout handler
165
- // todo: If forwarding request to proxy failed, remove the proxy from setSendToProxiesList
166
- log.info('triggerInterSchemeDiscoveryFlow is done:', { isOk, results, proxyNames, alsReq })
167
- this.stepInProgress('allSent-12')
168
-
169
- if (!isOk) {
150
+ const alsReq = await this.#setProxyListToCache(proxyNames, source, params)
151
+ const sentList = await this.#sendOutProxyRequests({ proxyNames, alsReq, headers, params })
152
+ if (sentList.length === 0) {
170
153
  throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.proxyConnectionError, log)
171
154
  }
155
+
156
+ log.info('triggerInterSchemeDiscoveryFlow is done:', { sentList, alsReq })
157
+ return sentList
172
158
  }
173
159
 
174
160
  isLocalSource () {
@@ -269,9 +255,29 @@ class GetPartiesService extends BasePartiesService {
269
255
  headers, sendTo, callbackEndpointType, RestMethods.GET, undefined, options, this.deps.childSpan
270
256
  )
271
257
  await this.#setProxyGetPartiesTimeout(sendTo)
258
+ this.log.debug('#forwardGetPartiesRequest is done:', { sendTo, sentResult })
272
259
  return sentResult
273
260
  }
274
261
 
262
+ async #sendOutProxyRequests ({ proxyNames, alsReq, headers, params }) {
263
+ this.stepInProgress('#sendOutProxyRequests')
264
+ const sentList = []
265
+
266
+ const sendProxyRequest = (sendTo) => this.#forwardGetPartiesRequest({ sendTo, headers, params })
267
+ .then(() => { sentList.push(sendTo) })
268
+ .catch(err => {
269
+ this.log.error(`error in sending request to proxy ${sendTo}: `, err)
270
+ return this.deps.proxyCache.receivedErrorResponse(alsReq, sendTo)
271
+ })
272
+ .catch(err => {
273
+ this.log.error(`failed to remove proxy ${sendTo} from proxyCache: `, err)
274
+ })
275
+ await Promise.all(proxyNames.map(sendProxyRequest))
276
+
277
+ this.log.verbose('#sendOutProxyRequests is done:', { sentList, proxyNames })
278
+ return sentList
279
+ }
280
+
275
281
  async #getFilteredProxyList (proxy) {
276
282
  this.stepInProgress('#getFilteredProxyList')
277
283
  if (!this.state.proxyEnabled) {
@@ -284,6 +290,18 @@ class GetPartiesService extends BasePartiesService {
284
290
  return proxyNames.filter(name => name !== proxy)
285
291
  }
286
292
 
293
+ async #setProxyListToCache (proxyNames, source, params) {
294
+ this.stepInProgress('#setProxyListToCache')
295
+ const alsReq = this.deps.partiesUtils.alsRequestDto(source, params)
296
+
297
+ const isCached = await this.deps.proxyCache.setSendToProxiesList(alsReq, proxyNames, proxyCacheTtlSec)
298
+ if (!isCached) {
299
+ throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.failedToCacheSendToProxiesList)
300
+ }
301
+ this.log.verbose('#setProxyListToCache is done: ', { alsReq, proxyNames, proxyCacheTtlSec })
302
+ return alsReq
303
+ }
304
+
287
305
  async #setProxyGetPartiesTimeout (sendTo) {
288
306
  const isLocalSource = this.isLocalSource()
289
307
  const isSentToProxy = this.state.destination !== sendTo
@@ -300,12 +318,3 @@ class GetPartiesService extends BasePartiesService {
300
318
  }
301
319
 
302
320
  module.exports = GetPartiesService
303
-
304
- // As Payee DFSP Scheme Oracle identifies direct participant.
305
- // As Payer DFSP Scheme oracle identifies interscheme participant.
306
-
307
- // zm-dfsp --> ZM
308
- // region-dfsp --> Region
309
- // mw-dfsp --> MW (mw-party-123)
310
-
311
- // 1. region-dfsp gets info about mw-party-123
@@ -68,7 +68,7 @@ class PutPartiesErrorService extends BasePartiesService {
68
68
  this.stepInProgress('checkLastProxyCallback')
69
69
  const { proxy } = this.state
70
70
  const isLast = await this.deps.proxyCache.receivedErrorResponse(alsReq, proxy)
71
- this.log.info(`got${isLast ? '' : 'NOT'} last error callback from proxy`, { proxy, alsReq, isLast })
71
+ this.log.info(`got ${isLast ? '' : 'NOT '}last inter-scheme error callback from a proxy`, { proxy, alsReq, isLast })
72
72
  return isLast
73
73
  }
74
74
 
@@ -25,10 +25,16 @@
25
25
  --------------
26
26
  ******/
27
27
 
28
- const { createMockDeps, createProxyCacheMock, oracleMock, participantMock } = require('./deps')
28
+ const {
29
+ createMockDeps,
30
+ createProxyCacheMock,
31
+ createProxiesUtilMock,
32
+ oracleMock,
33
+ participantMock
34
+ } = require('./deps')
29
35
  // ↑ should be first require to mock external deps ↑
30
36
  const { GetPartiesService } = require('#src/domain/parties/services/index')
31
- const { API_TYPES } = require('#src/constants')
37
+ const { API_TYPES, ERROR_MESSAGES } = require('#src/constants')
32
38
  const fixtures = require('#test/fixtures/index')
33
39
 
34
40
  const { RestMethods, Headers } = GetPartiesService.enums()
@@ -154,6 +160,45 @@ describe('GetPartiesService Tests -->', () => {
154
160
  })
155
161
  })
156
162
 
163
+ describe('triggerInterSchemeDiscoveryFlow Tests', () => {
164
+ test('should remove proxy from proxyCache if sending request to it fails', async () => {
165
+ expect.assertions(2)
166
+ participantMock.sendRequest = jest.fn().mockRejectedValue(new Error('Proxy error'))
167
+ const proxies = createProxiesUtilMock({
168
+ getAllProxiesNames: jest.fn().mockResolvedValue(['proxy-1'])
169
+ })
170
+ const deps = createMockDeps({ proxies })
171
+
172
+ const headers = fixtures.partiesCallHeadersDto({ destination: '' })
173
+ const params = fixtures.partiesParamsDto()
174
+ const service = new GetPartiesService(deps, { headers, params })
175
+
176
+ await expect(service.triggerInterSchemeDiscoveryFlow(headers))
177
+ .rejects.toThrow(ERROR_MESSAGES.proxyConnectionError)
178
+ expect(deps.proxyCache.receivedErrorResponse).toHaveBeenCalledTimes(1)
179
+ })
180
+
181
+ test('should NOT throw an error if at least one request is sent to a proxy', async () => {
182
+ participantMock.sendRequest = jest.fn()
183
+ .mockRejectedValueOnce(new Error('Proxy error'))
184
+ .mockResolvedValueOnce({})
185
+ const proxyOk = 'proxyOk'
186
+ const proxies = createProxiesUtilMock({
187
+ getAllProxiesNames: jest.fn().mockResolvedValue(['proxyErr', proxyOk])
188
+ })
189
+ const deps = createMockDeps({ proxies })
190
+
191
+ const headers = fixtures.partiesCallHeadersDto({ destination: '' })
192
+ const params = fixtures.partiesParamsDto()
193
+ const service = new GetPartiesService(deps, { headers, params })
194
+
195
+ const sentList = await service.triggerInterSchemeDiscoveryFlow(headers)
196
+ expect(sentList).toEqual([proxyOk])
197
+ expect(deps.proxyCache.receivedErrorResponse).toHaveBeenCalledTimes(1)
198
+ expect(participantMock.sendRequest.mock.lastCall[1]).toBe(proxyOk)
199
+ })
200
+ })
201
+
157
202
  describe('setProxyGetPartiesTimeout Tests', () => {
158
203
  test('should set getParties timeout for local source and external destination', async () => {
159
204
  participantMock.validateParticipant = jest.fn()