account-lookup-service 17.7.1 → 17.8.0-snapshot.100
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 +0 -7
- package/docker/mock-proxy/src/server.ts +13 -4
- package/package.json +12 -9
- package/src/constants.js +35 -2
- package/src/domain/parties/deps.js +11 -4
- package/src/domain/parties/getPartiesByTypeAndID.js +9 -13
- package/src/domain/parties/partiesUtils.js +4 -34
- package/src/domain/parties/putParties.js +26 -71
- package/src/domain/parties/services/BasePartiesService.js +146 -17
- package/src/domain/parties/services/GetPartiesService.js +213 -166
- package/src/domain/parties/services/PutPartiesErrorService.js +52 -28
- package/src/domain/parties/services/PutPartiesService.js +51 -33
- package/src/domain/parties/services/TimeoutPartiesService.js +84 -0
- package/src/domain/parties/services/index.js +3 -1
- package/src/domain/timeout/createSpan.js +55 -0
- package/src/domain/timeout/index.js +27 -36
- package/src/handlers/TimeoutHandler.js +2 -2
- package/src/index.js +3 -0
- package/src/lib/util.js +11 -3
- package/src/server.js +16 -5
- package/test/fixtures/index.js +53 -3
- package/test/integration/api/parties.test.js +1 -0
- package/test/integration/domain/timeout/index.test.js +83 -28
- package/test/unit/domain/parties/parties.test.js +27 -20
- package/test/unit/domain/parties/partiesUtils.test.js +51 -0
- package/test/unit/domain/parties/services/BasePartiesService.test.js +72 -0
- package/test/unit/domain/parties/services/GetPartiesService.test.js +340 -0
- package/test/unit/domain/parties/services/PutPartiesErrorService.test.js +50 -0
- package/test/unit/domain/parties/services/TimeoutPartiesService.test.js +72 -0
- package/test/unit/domain/parties/services/deps.js +51 -0
- package/test/unit/domain/timeout/index.test.js +17 -12
- package/test/util/apiClients/AlsApiClient.js +6 -4
- package/test/util/apiClients/BasicApiClient.js +33 -6
- package/test/util/apiClients/ProxyApiClient.js +46 -1
- package/test/util/index.js +5 -6
- package/test/util/mockDeps.js +72 -0
- package/src/domain/timeout/dto.js +0 -54
- package/test/unit/domain/parties/utils.test.js +0 -60
- package/test/unit/domain/timeout/dto.test.js +0 -24
@@ -25,185 +25,270 @@
|
|
25
25
|
--------------
|
26
26
|
******/
|
27
27
|
|
28
|
-
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
29
28
|
const { ERROR_MESSAGES } = require('../../../constants')
|
30
|
-
const { createCallbackHeaders } = require('../../../lib/headers')
|
31
29
|
const BasePartiesService = require('./BasePartiesService')
|
32
30
|
|
33
|
-
const {
|
34
|
-
FspEndpointTypes, FspEndpointTemplates,
|
35
|
-
Headers, RestMethods
|
36
|
-
} = BasePartiesService.enums()
|
37
|
-
|
31
|
+
const { FspEndpointTypes, RestMethods } = BasePartiesService.enums()
|
38
32
|
const proxyCacheTtlSec = 40 // todo: make configurable
|
39
33
|
|
40
34
|
class GetPartiesService extends BasePartiesService {
|
41
|
-
async handleRequest (
|
42
|
-
const source =
|
43
|
-
const proxy = headers[Headers.FSPIOP.PROXY]
|
44
|
-
const destination = headers[Headers.FSPIOP.DESTINATION]
|
35
|
+
async handleRequest () {
|
36
|
+
const { destination, source, proxy } = this.state
|
45
37
|
// see https://github.com/mojaloop/design-authority/issues/79
|
46
38
|
// the requester has specified a destination routing header. We should respect that and forward the request directly to the destination
|
47
39
|
// without consulting any oracles.
|
48
|
-
this.log.info('handling getParties request', { source, destination, proxy })
|
49
|
-
|
50
|
-
const requester = await this.validateRequester({ source, proxy })
|
51
|
-
results.requester = requester
|
40
|
+
this.log.info('handling getParties request...', { source, destination, proxy })
|
41
|
+
this.state.requester = await this.validateRequester()
|
52
42
|
|
53
43
|
if (destination) {
|
54
|
-
await this.forwardRequestToDestination(
|
55
|
-
return
|
56
|
-
}
|
57
|
-
const response = await this.sendOracleDiscoveryRequest({ headers, params, query })
|
58
|
-
|
59
|
-
if (Array.isArray(response?.data?.partyList) && response.data.partyList.length > 0) {
|
60
|
-
const partyList = this.filterOraclePartyList({ response, params })
|
61
|
-
await this.processOraclePartyList({ partyList, headers, params, destination })
|
44
|
+
await this.forwardRequestToDestination()
|
62
45
|
return
|
63
46
|
}
|
64
47
|
|
65
|
-
|
66
|
-
const
|
48
|
+
const response = await this.sendOracleDiscoveryRequest()
|
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
|
67
52
|
|
68
|
-
|
69
|
-
|
70
|
-
|
53
|
+
const fspiopError = await this.triggerInterSchemeDiscoveryFlow(this.inputs.headers)
|
54
|
+
if (fspiopError) {
|
55
|
+
this.state.fspiopError = fspiopError // todo: think, if we need this
|
71
56
|
}
|
72
|
-
|
73
|
-
results.fspiopError = await this.sendPartyNotFoundErrorCallback({ requester, headers, params })
|
74
57
|
}
|
75
58
|
|
76
|
-
async validateRequester (
|
77
|
-
this.
|
59
|
+
async validateRequester () {
|
60
|
+
const { source, proxy, proxyEnabled } = this.state
|
78
61
|
const log = this.log.child({ source, proxy, method: 'validateRequester' })
|
62
|
+
this.stepInProgress('validateRequester-0')
|
79
63
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
64
|
+
if (!(proxyEnabled && proxy)) {
|
65
|
+
const schemeSource = await this.validateParticipant(source)
|
66
|
+
if (schemeSource) {
|
67
|
+
log.debug('source participant is in scheme')
|
68
|
+
return source
|
69
|
+
}
|
84
70
|
}
|
85
71
|
|
86
|
-
if (!
|
87
|
-
|
88
|
-
log.warn(errMessage)
|
89
|
-
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
72
|
+
if (!proxyEnabled || !proxy) {
|
73
|
+
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.sourceFspNotFound, log)
|
90
74
|
}
|
91
75
|
|
92
|
-
const
|
93
|
-
if (!
|
94
|
-
|
95
|
-
log.warn(errMessage)
|
96
|
-
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
76
|
+
const schemeProxy = await this.validateParticipant(proxy)
|
77
|
+
if (!schemeProxy) {
|
78
|
+
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.partyProxyNotFound, log)
|
97
79
|
}
|
98
80
|
|
99
81
|
const isCached = await this.deps.proxyCache.addDfspIdToProxyMapping(source, proxy)
|
100
82
|
if (!isCached) {
|
101
|
-
|
102
|
-
log.warn(errMessage)
|
103
|
-
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
83
|
+
throw super.createFspiopIdNotFoundError('failed to addDfspIdToProxyMapping', log)
|
104
84
|
}
|
105
85
|
|
106
|
-
log.info('source is added to proxyMapping cache
|
86
|
+
log.info('source is added to proxyMapping cache')
|
107
87
|
return proxy
|
108
88
|
}
|
109
89
|
|
110
|
-
async forwardRequestToDestination (
|
111
|
-
this.
|
90
|
+
async forwardRequestToDestination () {
|
91
|
+
const { headers, params } = this.inputs
|
92
|
+
const { destination } = this.state
|
112
93
|
const log = this.log.child({ method: 'forwardRequestToDestination' })
|
113
94
|
let sendTo = destination
|
114
95
|
|
115
|
-
const
|
116
|
-
if (!
|
117
|
-
this.
|
118
|
-
const proxyId = this.proxyEnabled && await this.deps.proxyCache.lookupProxyByDfspId(destination)
|
96
|
+
const schemeParticipant = await this.validateParticipant(destination)
|
97
|
+
if (!schemeParticipant) {
|
98
|
+
this.stepInProgress('lookupProxyDestination-2')
|
99
|
+
const proxyId = this.state.proxyEnabled && await this.deps.proxyCache.lookupProxyByDfspId(destination)
|
119
100
|
|
120
101
|
if (!proxyId) {
|
121
|
-
log.warn('
|
122
|
-
|
123
|
-
|
102
|
+
log.warn('destination participant is not in scheme, and no dfsp-to-proxy mapping', { destination })
|
103
|
+
await super.sendDeleteOracleRequest(headers, params)
|
104
|
+
await this.triggerInterSchemeDiscoveryFlow(GetPartiesService.headersWithoutDestination(headers))
|
105
|
+
return
|
124
106
|
}
|
125
107
|
sendTo = proxyId
|
126
108
|
}
|
127
|
-
|
109
|
+
|
128
110
|
await this.#forwardGetPartiesRequest({ sendTo, headers, params })
|
129
111
|
log.info('discovery getPartiesByTypeAndID request was sent', { sendTo })
|
130
112
|
}
|
131
113
|
|
132
|
-
|
133
|
-
|
134
|
-
this.
|
114
|
+
async sendOracleDiscoveryRequest () {
|
115
|
+
this.stepInProgress('#sendOracleDiscoveryRequest')
|
116
|
+
const { headers, params, query } = this.inputs
|
117
|
+
return this.deps.oracle.oracleRequest(headers, RestMethods.GET, params, query, undefined, this.deps.cache)
|
118
|
+
}
|
119
|
+
|
120
|
+
async processOraclePartyListResponse (response) {
|
121
|
+
if (!Array.isArray(response?.data?.partyList) || response.data.partyList.length === 0) {
|
122
|
+
this.log.verbose('oracle partyList is empty')
|
123
|
+
return false
|
124
|
+
}
|
125
|
+
|
126
|
+
this.stepInProgress('processOraclePartyList')
|
127
|
+
const partyList = this.#filterOraclePartyList(response)
|
128
|
+
|
129
|
+
let sentCount = 0
|
130
|
+
await Promise.all(partyList.map(async party => {
|
131
|
+
const isSent = await this.#processSingleOracleParty(party)
|
132
|
+
if (isSent) sentCount++
|
133
|
+
}))
|
134
|
+
|
135
|
+
const isSent = sentCount > 0
|
136
|
+
this.log.verbose('processOraclePartyList is done', { isSent, sentCount })
|
137
|
+
// if NOT isSent, need to trigger interScheme discovery flow
|
138
|
+
return isSent
|
139
|
+
}
|
140
|
+
|
141
|
+
async triggerInterSchemeDiscoveryFlow (headers) {
|
142
|
+
const { params } = this.inputs
|
143
|
+
const { proxy, source } = this.state
|
144
|
+
const log = this.log.child({ source })
|
145
|
+
log.verbose('triggerInterSchemeDiscoveryFlow start...', { proxy })
|
146
|
+
|
147
|
+
const proxyNames = await this.#getFilteredProxyList(proxy)
|
148
|
+
if (!proxyNames.length) {
|
149
|
+
return this.#sendPartyNotFoundErrorCallback(headers)
|
150
|
+
}
|
151
|
+
|
152
|
+
const alsReq = await this.#setProxyListToCache(proxyNames, source, params)
|
153
|
+
const { sentList, wasLast } = await this.#sendOutProxyRequests({ proxyNames, alsReq, headers, params })
|
154
|
+
if (sentList.length === 0) {
|
155
|
+
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.proxyConnectionError, log)
|
156
|
+
}
|
157
|
+
if (wasLast) {
|
158
|
+
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.noSuccessfulProxyDiscoveryResponses, log)
|
159
|
+
}
|
160
|
+
|
161
|
+
log.info('triggerInterSchemeDiscoveryFlow is done:', { sentList, alsReq })
|
162
|
+
return sentList
|
163
|
+
}
|
164
|
+
|
165
|
+
isLocalSource () {
|
166
|
+
const isLocal = this.state.source === this.state.requester
|
167
|
+
this.log.debug(`isLocalSource: ${isLocal}`)
|
168
|
+
return isLocal
|
169
|
+
}
|
170
|
+
|
171
|
+
#filterOraclePartyList (response) {
|
172
|
+
// Oracle's API is a standard rest-style end-point Thus a GET /party on the oracle will return all participant-party records.
|
173
|
+
// We must filter the results based on the callbackEndpointType to make sure we remove records containing partySubIdOrType when we are in FSPIOP_CALLBACK_URL_PARTIES_GET mode:
|
174
|
+
this.stepInProgress('filterOraclePartyList')
|
175
|
+
const { params } = this.inputs
|
135
176
|
const callbackEndpointType = this.deps.partiesUtils.getPartyCbType(params.SubId)
|
136
|
-
let
|
177
|
+
let filteredPartyList
|
137
178
|
|
138
179
|
switch (callbackEndpointType) {
|
139
180
|
case FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_GET:
|
140
|
-
|
181
|
+
filteredPartyList = response.data.partyList.filter(party => party.partySubIdOrType == null) // Filter records that DON'T contain a partySubIdOrType
|
141
182
|
break
|
142
183
|
case FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_GET:
|
143
|
-
|
184
|
+
filteredPartyList = response.data.partyList.filter(party => party.partySubIdOrType === params.SubId) // Filter records that match partySubIdOrType
|
144
185
|
break
|
145
186
|
default:
|
146
|
-
|
187
|
+
filteredPartyList = response // Fallback to providing the standard list
|
147
188
|
}
|
148
189
|
|
149
|
-
if (!Array.isArray(
|
150
|
-
|
151
|
-
this.log.warn(errMessage)
|
152
|
-
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
190
|
+
if (!Array.isArray(filteredPartyList) || !filteredPartyList.length) {
|
191
|
+
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.emptyFilteredPartyList)
|
153
192
|
}
|
154
193
|
|
155
|
-
return
|
194
|
+
return filteredPartyList
|
156
195
|
}
|
157
196
|
|
158
|
-
|
159
|
-
|
197
|
+
/** @returns {Promise<boolean>} - is request forwarded to participant */
|
198
|
+
async #processSingleOracleParty (party) {
|
199
|
+
const { headers, params } = this.inputs
|
200
|
+
const { fspId } = party
|
201
|
+
|
202
|
+
const schemeParticipant = await this.validateParticipant(fspId)
|
203
|
+
if (schemeParticipant) {
|
204
|
+
this.log.info('participant is in scheme, so forwarding to it...', { fspId })
|
205
|
+
await this.#forwardGetPartiesRequest({
|
206
|
+
sendTo: fspId,
|
207
|
+
headers: GetPartiesService.overrideDestinationHeader(headers, fspId),
|
208
|
+
params
|
209
|
+
})
|
210
|
+
return true
|
211
|
+
}
|
160
212
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
213
|
+
if (this.state.proxyEnabled) {
|
214
|
+
const proxyName = await this.deps.proxyCache.lookupProxyByDfspId(fspId)
|
215
|
+
if (!proxyName) {
|
216
|
+
this.log.warn('no proxyMapping for external DFSP! Deleting reference in oracle...', { fspId })
|
217
|
+
await super.sendDeleteOracleRequest(headers, params)
|
218
|
+
// todo: check if it won't delete all parties
|
219
|
+
return false
|
167
220
|
}
|
168
|
-
|
169
|
-
|
170
|
-
if (
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
221
|
+
|
222
|
+
// Coz there's no destination header, it means we're inside initial inter-scheme discovery phase.
|
223
|
+
// So we should proceed only if source is in scheme (local participant)
|
224
|
+
const isLocalSource = this.isLocalSource()
|
225
|
+
if (isLocalSource) {
|
226
|
+
this.log.info('participant is NOT in scheme, but source is. So forwarding to proxy...', { fspId, proxyName })
|
227
|
+
await this.#forwardGetPartiesRequest({ // todo: add timeout if sendTo is proxy
|
228
|
+
sendTo: proxyName,
|
229
|
+
headers: GetPartiesService.overrideDestinationHeader(headers, fspId),
|
176
230
|
params
|
177
231
|
})
|
232
|
+
return true
|
178
233
|
}
|
234
|
+
}
|
235
|
+
return false
|
236
|
+
}
|
179
237
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
sendTo: proxyName,
|
193
|
-
headers: clonedHeaders,
|
194
|
-
params
|
195
|
-
})
|
196
|
-
}
|
197
|
-
}
|
238
|
+
async #sendPartyNotFoundErrorCallback (headers) {
|
239
|
+
const { params } = this.inputs
|
240
|
+
const callbackHeaders = GetPartiesService.createErrorCallbackHeaders(headers, params)
|
241
|
+
const fspiopError = super.createFspiopIdNotFoundError('No proxy found to start inter-scheme discovery flow')
|
242
|
+
const errorInfo = await this.deps.partiesUtils.makePutPartiesErrorPayload(
|
243
|
+
this.deps.config, fspiopError, callbackHeaders, params
|
244
|
+
)
|
245
|
+
|
246
|
+
await this.sendErrorCallback({
|
247
|
+
errorInfo,
|
248
|
+
headers: callbackHeaders,
|
249
|
+
params
|
198
250
|
})
|
199
|
-
|
200
|
-
log.verbose('processOraclePartyList is done', { sentCount })
|
201
|
-
// todo: think what if sentCount === 0 here
|
251
|
+
return fspiopError
|
202
252
|
}
|
203
253
|
|
204
|
-
async
|
205
|
-
this.
|
206
|
-
|
254
|
+
async #forwardGetPartiesRequest ({ sendTo, headers, params }) {
|
255
|
+
this.stepInProgress('#forwardGetPartiesRequest')
|
256
|
+
const callbackEndpointType = this.deps.partiesUtils.getPartyCbType(params.SubId)
|
257
|
+
const options = this.deps.partiesUtils.partiesRequestOptionsDto(params)
|
258
|
+
|
259
|
+
const sentResult = await this.deps.participant.sendRequest(
|
260
|
+
headers, sendTo, callbackEndpointType, RestMethods.GET, undefined, options, this.deps.childSpan
|
261
|
+
)
|
262
|
+
await this.#setProxyGetPartiesTimeout(sendTo)
|
263
|
+
this.log.debug('#forwardGetPartiesRequest is done:', { sendTo, sentResult })
|
264
|
+
return sentResult
|
265
|
+
}
|
266
|
+
|
267
|
+
async #sendOutProxyRequests ({ proxyNames, alsReq, headers, params }) {
|
268
|
+
this.stepInProgress('#sendOutProxyRequests')
|
269
|
+
const sentList = []
|
270
|
+
let wasLast = false // if any failed proxy request was last
|
271
|
+
|
272
|
+
const sendProxyRequest = (sendTo) => this.#forwardGetPartiesRequest({ sendTo, headers, params })
|
273
|
+
.then(() => { sentList.push(sendTo) })
|
274
|
+
.catch(err => {
|
275
|
+
this.log.error(`error in sending request to proxy ${sendTo}: `, err)
|
276
|
+
this.log.verbose(`removing proxy ${sendTo} from proxyCache...`)
|
277
|
+
return this.deps.proxyCache.receivedErrorResponse(alsReq, sendTo)
|
278
|
+
})
|
279
|
+
.then((isLast) => { wasLast = isLast })
|
280
|
+
.catch(err => {
|
281
|
+
this.log.error(`failed to remove proxy ${sendTo} from proxyCache: `, err)
|
282
|
+
})
|
283
|
+
await Promise.all(proxyNames.map(sendProxyRequest))
|
284
|
+
|
285
|
+
this.log.verbose('#sendOutProxyRequests is done:', { sentList, wasLast, proxyNames })
|
286
|
+
return { sentList, wasLast }
|
287
|
+
}
|
288
|
+
|
289
|
+
async #getFilteredProxyList (proxy) {
|
290
|
+
this.stepInProgress('#getFilteredProxyList')
|
291
|
+
if (!this.state.proxyEnabled) {
|
207
292
|
this.log.warn('proxyCache is not enabled')
|
208
293
|
return []
|
209
294
|
}
|
@@ -213,68 +298,30 @@ class GetPartiesService extends BasePartiesService {
|
|
213
298
|
return proxyNames.filter(name => name !== proxy)
|
214
299
|
}
|
215
300
|
|
216
|
-
async
|
217
|
-
|
218
|
-
this.deps.stepState.inProgress('setSendToProxiesList-10')
|
301
|
+
async #setProxyListToCache (proxyNames, source, params) {
|
302
|
+
this.stepInProgress('#setProxyListToCache')
|
219
303
|
const alsReq = this.deps.partiesUtils.alsRequestDto(source, params)
|
220
|
-
log.info('starting setSendToProxiesList flow: ', { proxyNames, alsReq, proxyCacheTtlSec })
|
221
304
|
|
222
305
|
const isCached = await this.deps.proxyCache.setSendToProxiesList(alsReq, proxyNames, proxyCacheTtlSec)
|
223
306
|
if (!isCached) {
|
224
|
-
|
225
|
-
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, ERROR_MESSAGES.failedToCacheSendToProxiesList)
|
226
|
-
}
|
227
|
-
|
228
|
-
this.deps.stepState.inProgress('sendingProxyRequests-11')
|
229
|
-
const sending = proxyNames.map(
|
230
|
-
sendTo => this.#forwardGetPartiesRequest({ sendTo, headers, params })
|
231
|
-
.then(({ status, data } = {}) => ({ status, data }))
|
232
|
-
)
|
233
|
-
const results = await Promise.allSettled(sending)
|
234
|
-
const isOk = results.some(result => result.status === 'fulfilled')
|
235
|
-
// If, at least, one request is sent to proxy, we treat the whole flow as successful.
|
236
|
-
// Failed requests should be handled by TTL expired/timeout handler
|
237
|
-
// todo: - think, if we should handle failed requests here (e.g., by calling receivedErrorResponse)
|
238
|
-
log.info('triggerSendToProxiesFlow is done:', { isOk, results, proxyNames, alsReq })
|
239
|
-
this.deps.stepState.inProgress('allSent-12')
|
240
|
-
if (!isOk) {
|
241
|
-
log.warn('no successful requests sent to proxies')
|
242
|
-
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, ERROR_MESSAGES.proxyConnectionError)
|
307
|
+
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.failedToCacheSendToProxiesList)
|
243
308
|
}
|
309
|
+
this.log.verbose('#setProxyListToCache is done: ', { alsReq, proxyNames, proxyCacheTtlSec })
|
310
|
+
return alsReq
|
244
311
|
}
|
245
312
|
|
246
|
-
async
|
247
|
-
this.
|
248
|
-
const
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
await this.sendErrorCallback({
|
259
|
-
sendTo: requester,
|
260
|
-
errorInfo: fspiopError.toApiErrorObject(this.deps.config.ERROR_HANDLING),
|
261
|
-
headers: callbackHeaders,
|
262
|
-
params
|
263
|
-
})
|
264
|
-
return fspiopError
|
265
|
-
}
|
266
|
-
|
267
|
-
async sendOracleDiscoveryRequest ({ headers, params, query }) {
|
268
|
-
this.deps.stepState.inProgress('oracleRequest-4')
|
269
|
-
return this.deps.oracle.oracleRequest(headers, RestMethods.GET, params, query, undefined, this.deps.cache)
|
270
|
-
}
|
271
|
-
|
272
|
-
async #forwardGetPartiesRequest ({ sendTo, headers, params }) {
|
273
|
-
this.deps.stepState.inProgress('forwardRequest-3')
|
274
|
-
const callbackEndpointType = this.deps.partiesUtils.getPartyCbType(params.SubId)
|
275
|
-
const options = this.deps.partiesUtils.partiesRequestOptionsDto(params)
|
276
|
-
|
277
|
-
return this.deps.participant.sendRequest(headers, sendTo, callbackEndpointType, RestMethods.GET, undefined, options, this.deps.childSpan)
|
313
|
+
async #setProxyGetPartiesTimeout (sendTo) {
|
314
|
+
const isLocalSource = this.isLocalSource()
|
315
|
+
const isSentToProxy = this.state.destination !== sendTo
|
316
|
+
this.log.verbose('isLocalSource and isSentToProxy: ', { isLocalSource, isSentToProxy, sendTo })
|
317
|
+
|
318
|
+
if (isSentToProxy && isLocalSource) {
|
319
|
+
this.stepInProgress('#setProxyGetPartiesTimeout')
|
320
|
+
const alsReq = this.deps.partiesUtils.alsRequestDto(this.state.source, this.inputs.params)
|
321
|
+
const isSet = await this.deps.proxyCache.setProxyGetPartiesTimeout(alsReq, sendTo)
|
322
|
+
this.log.info('#setProxyGetPartiesTimeout is done', { isSet })
|
323
|
+
return isSet
|
324
|
+
}
|
278
325
|
}
|
279
326
|
}
|
280
327
|
|
@@ -30,49 +30,73 @@ const { ERROR_MESSAGES } = require('../../../constants')
|
|
30
30
|
const BasePartiesService = require('./BasePartiesService')
|
31
31
|
|
32
32
|
class PutPartiesErrorService extends BasePartiesService {
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
33
|
+
/** @returns {Promise<true | undefined>} - If true, need to trigger inter-scheme discovery. */
|
34
|
+
async handleRequest () {
|
35
|
+
if (this.state.proxyEnabled && this.state.proxy) {
|
36
|
+
const alsReq = this.deps.partiesUtils.alsRequestDto(this.state.destination, this.inputs.params) // or source?
|
37
|
+
const isPending = await this.deps.proxyCache.isPendingCallback(alsReq)
|
38
|
+
|
39
|
+
if (!isPending) {
|
40
|
+
// not initial inter-scheme discovery case. Cleanup oracle and trigger inter-scheme discovery
|
41
|
+
this.log.warn('Need to cleanup oracle and trigger new inter-scheme discovery flow')
|
42
|
+
await this.cleanupOracle()
|
43
|
+
await this.removeProxyGetPartiesTimeoutCache(alsReq)
|
44
|
+
return true // need to trigger inter-scheme discovery
|
45
|
+
}
|
46
|
+
|
47
|
+
const isLast = await this.checkLastProxyCallback(alsReq)
|
48
|
+
if (!isLast) {
|
49
|
+
this.log.verbose('putPartiesErrorByTypeAndID proxy callback was processed')
|
50
|
+
return
|
51
|
+
}
|
44
52
|
}
|
45
|
-
|
53
|
+
|
54
|
+
await this.identifyDestinationForErrorCallback()
|
55
|
+
await this.sendErrorCallbackToParticipant()
|
56
|
+
this.log.info('putPartiesByTypeAndID is done')
|
46
57
|
}
|
47
58
|
|
48
|
-
async
|
49
|
-
this.
|
50
|
-
const
|
59
|
+
async cleanupOracle () {
|
60
|
+
this.stepInProgress('cleanupOracle')
|
61
|
+
const { headers, params, payload } = this.inputs
|
62
|
+
this.log.info('cleanupOracle due to error callback...', { payload })
|
63
|
+
const swappedHeaders = this.deps.partiesUtils.swapSourceDestinationHeaders(headers)
|
64
|
+
await super.sendDeleteOracleRequest(swappedHeaders, params)
|
65
|
+
}
|
66
|
+
|
67
|
+
async checkLastProxyCallback (alsReq) {
|
68
|
+
this.stepInProgress('checkLastProxyCallback')
|
69
|
+
const { proxy } = this.state
|
51
70
|
const isLast = await this.deps.proxyCache.receivedErrorResponse(alsReq, proxy)
|
52
|
-
this.log.info(`got${isLast ? '' : 'NOT'}
|
71
|
+
this.log.info(`got ${isLast ? '' : 'NOT '}last inter-scheme error callback from a proxy`, { proxy, alsReq, isLast })
|
53
72
|
return isLast
|
54
73
|
}
|
55
74
|
|
56
|
-
async identifyDestinationForErrorCallback (
|
57
|
-
this.
|
58
|
-
const
|
59
|
-
|
75
|
+
async identifyDestinationForErrorCallback () {
|
76
|
+
this.stepInProgress('identifyDestinationForErrorCallback')
|
77
|
+
const { destination } = this.state
|
78
|
+
const schemeParticipant = await super.validateParticipant(destination)
|
79
|
+
if (schemeParticipant) {
|
80
|
+
this.state.requester = destination
|
81
|
+
return
|
82
|
+
}
|
60
83
|
|
61
|
-
this.
|
62
|
-
const proxyName = this.proxyEnabled && await this.deps.proxyCache.lookupProxyByDfspId(destination)
|
63
|
-
if (proxyName)
|
84
|
+
this.stepInProgress('lookupProxyDestination-4')
|
85
|
+
const proxyName = this.state.proxyEnabled && await this.deps.proxyCache.lookupProxyByDfspId(destination)
|
86
|
+
if (proxyName) {
|
87
|
+
this.state.requester = proxyName
|
88
|
+
return
|
89
|
+
}
|
64
90
|
|
65
91
|
const errMessage = ERROR_MESSAGES.partyDestinationFspNotFound
|
66
92
|
this.log.warn(errMessage, { destination })
|
67
93
|
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.DESTINATION_FSP_ERROR, errMessage)
|
68
94
|
}
|
69
95
|
|
70
|
-
async sendErrorCallbackToParticipant (
|
71
|
-
this.
|
96
|
+
async sendErrorCallbackToParticipant () {
|
97
|
+
const { headers, params, dataUri } = this.inputs
|
72
98
|
const errorInfo = PutPartiesErrorService.decodeDataUriPayload(dataUri)
|
73
|
-
return super.sendErrorCallback({
|
74
|
-
sendTo, errorInfo, headers, params
|
75
|
-
})
|
99
|
+
return super.sendErrorCallback({ errorInfo, headers, params })
|
76
100
|
}
|
77
101
|
}
|
78
102
|
|