account-lookup-service 17.7.0 → 17.8.0-snapshot.10
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/docker/mock-proxy/src/server.ts +13 -4
- package/package.json +11 -8
- 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 +143 -15
- package/src/domain/parties/services/GetPartiesService.js +210 -165
- 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/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 +26 -18
- package/test/unit/domain/parties/partiesUtils.test.js +51 -0
- package/test/unit/domain/parties/services/BasePartiesService.test.js +71 -0
- package/test/unit/domain/parties/services/GetPartiesService.test.js +316 -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,268 @@
|
|
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
|
-
const
|
81
|
-
if (
|
82
|
-
log.debug('source is in scheme')
|
64
|
+
const schemeSource = await this.validateParticipant(source)
|
65
|
+
if (schemeSource) {
|
66
|
+
log.debug('source participant is in scheme')
|
83
67
|
return source
|
84
68
|
}
|
85
69
|
|
86
|
-
if (!
|
87
|
-
|
88
|
-
log.warn(errMessage)
|
89
|
-
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
70
|
+
if (!proxyEnabled || !proxy) {
|
71
|
+
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.sourceFspNotFound, log)
|
90
72
|
}
|
91
73
|
|
92
|
-
const
|
93
|
-
if (!
|
94
|
-
|
95
|
-
log.warn(errMessage)
|
96
|
-
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
74
|
+
const schemeProxy = await this.validateParticipant(proxy)
|
75
|
+
if (!schemeProxy) {
|
76
|
+
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.partyProxyNotFound, log)
|
97
77
|
}
|
98
78
|
|
99
79
|
const isCached = await this.deps.proxyCache.addDfspIdToProxyMapping(source, proxy)
|
100
80
|
if (!isCached) {
|
101
|
-
|
102
|
-
log.warn(errMessage)
|
103
|
-
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
81
|
+
throw super.createFspiopIdNotFoundError('failed to addDfspIdToProxyMapping', log)
|
104
82
|
}
|
105
83
|
|
106
|
-
log.info('source is added to proxyMapping cache
|
84
|
+
log.info('source is added to proxyMapping cache')
|
107
85
|
return proxy
|
108
86
|
}
|
109
87
|
|
110
|
-
async forwardRequestToDestination (
|
111
|
-
this.
|
88
|
+
async forwardRequestToDestination () {
|
89
|
+
const { headers, params } = this.inputs
|
90
|
+
const { destination } = this.state
|
112
91
|
const log = this.log.child({ method: 'forwardRequestToDestination' })
|
113
92
|
let sendTo = destination
|
114
93
|
|
115
|
-
const
|
116
|
-
if (!
|
117
|
-
this.
|
118
|
-
const proxyId = this.proxyEnabled && await this.deps.proxyCache.lookupProxyByDfspId(destination)
|
94
|
+
const schemeParticipant = await this.validateParticipant(destination)
|
95
|
+
if (!schemeParticipant) {
|
96
|
+
this.stepInProgress('lookupProxyDestination-2')
|
97
|
+
const proxyId = this.state.proxyEnabled && await this.deps.proxyCache.lookupProxyByDfspId(destination)
|
119
98
|
|
120
99
|
if (!proxyId) {
|
121
|
-
log.warn('
|
122
|
-
|
123
|
-
|
100
|
+
log.warn('destination participant is not in scheme, and no dfsp-to-proxy mapping', { destination })
|
101
|
+
await super.sendDeleteOracleRequest(headers, params)
|
102
|
+
await this.triggerInterSchemeDiscoveryFlow(GetPartiesService.headersWithoutDestination(headers))
|
103
|
+
return
|
124
104
|
}
|
125
105
|
sendTo = proxyId
|
126
106
|
}
|
127
|
-
|
107
|
+
|
128
108
|
await this.#forwardGetPartiesRequest({ sendTo, headers, params })
|
129
109
|
log.info('discovery getPartiesByTypeAndID request was sent', { sendTo })
|
130
110
|
}
|
131
111
|
|
132
|
-
|
133
|
-
|
134
|
-
this.
|
112
|
+
async sendOracleDiscoveryRequest () {
|
113
|
+
this.stepInProgress('#sendOracleDiscoveryRequest')
|
114
|
+
const { headers, params, query } = this.inputs
|
115
|
+
return this.deps.oracle.oracleRequest(headers, RestMethods.GET, params, query, undefined, this.deps.cache)
|
116
|
+
}
|
117
|
+
|
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
|
+
|
124
|
+
this.stepInProgress('processOraclePartyList')
|
125
|
+
const partyList = this.#filterOraclePartyList(response)
|
126
|
+
|
127
|
+
let sentCount = 0
|
128
|
+
await Promise.all(partyList.map(async party => {
|
129
|
+
const isSent = await this.#processSingleOracleParty(party)
|
130
|
+
if (isSent) sentCount++
|
131
|
+
}))
|
132
|
+
|
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
|
137
|
+
}
|
138
|
+
|
139
|
+
async triggerInterSchemeDiscoveryFlow (headers) {
|
140
|
+
const { params } = this.inputs
|
141
|
+
const { proxy, source } = this.state
|
142
|
+
const log = this.log.child({ source })
|
143
|
+
log.verbose('triggerInterSchemeDiscoveryFlow start...', { proxy })
|
144
|
+
|
145
|
+
const proxyNames = await this.#getFilteredProxyList(proxy)
|
146
|
+
if (!proxyNames.length) {
|
147
|
+
return this.#sendPartyNotFoundErrorCallback(headers)
|
148
|
+
}
|
149
|
+
|
150
|
+
const alsReq = await this.#setProxyListToCache(proxyNames, source, params)
|
151
|
+
const { sentList, wasLast } = await this.#sendOutProxyRequests({ proxyNames, alsReq, headers, params })
|
152
|
+
if (sentList.length === 0) {
|
153
|
+
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.proxyConnectionError, log)
|
154
|
+
}
|
155
|
+
if (wasLast) {
|
156
|
+
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.noSuccessfulProxyDiscoveryResponses, log)
|
157
|
+
}
|
158
|
+
|
159
|
+
log.info('triggerInterSchemeDiscoveryFlow is done:', { sentList, alsReq })
|
160
|
+
return sentList
|
161
|
+
}
|
162
|
+
|
163
|
+
isLocalSource () {
|
164
|
+
const isLocal = this.state.source === this.state.requester
|
165
|
+
this.log.debug(`isLocalSource: ${isLocal}`)
|
166
|
+
return isLocal
|
167
|
+
}
|
168
|
+
|
169
|
+
#filterOraclePartyList (response) {
|
170
|
+
// Oracle's API is a standard rest-style end-point Thus a GET /party on the oracle will return all participant-party records.
|
171
|
+
// 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:
|
172
|
+
this.stepInProgress('filterOraclePartyList')
|
173
|
+
const { params } = this.inputs
|
135
174
|
const callbackEndpointType = this.deps.partiesUtils.getPartyCbType(params.SubId)
|
136
|
-
let
|
175
|
+
let filteredPartyList
|
137
176
|
|
138
177
|
switch (callbackEndpointType) {
|
139
178
|
case FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_GET:
|
140
|
-
|
179
|
+
filteredPartyList = response.data.partyList.filter(party => party.partySubIdOrType == null) // Filter records that DON'T contain a partySubIdOrType
|
141
180
|
break
|
142
181
|
case FspEndpointTypes.FSPIOP_CALLBACK_URL_PARTIES_SUB_ID_GET:
|
143
|
-
|
182
|
+
filteredPartyList = response.data.partyList.filter(party => party.partySubIdOrType === params.SubId) // Filter records that match partySubIdOrType
|
144
183
|
break
|
145
184
|
default:
|
146
|
-
|
185
|
+
filteredPartyList = response // Fallback to providing the standard list
|
147
186
|
}
|
148
187
|
|
149
|
-
if (!Array.isArray(
|
150
|
-
|
151
|
-
this.log.warn(errMessage)
|
152
|
-
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.ID_NOT_FOUND, errMessage)
|
188
|
+
if (!Array.isArray(filteredPartyList) || !filteredPartyList.length) {
|
189
|
+
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.emptyFilteredPartyList)
|
153
190
|
}
|
154
191
|
|
155
|
-
return
|
192
|
+
return filteredPartyList
|
156
193
|
}
|
157
194
|
|
158
|
-
|
159
|
-
|
195
|
+
/** @returns {Promise<boolean>} - is request forwarded to participant */
|
196
|
+
async #processSingleOracleParty (party) {
|
197
|
+
const { headers, params } = this.inputs
|
198
|
+
const { fspId } = party
|
199
|
+
|
200
|
+
const schemeParticipant = await this.validateParticipant(fspId)
|
201
|
+
if (schemeParticipant) {
|
202
|
+
this.log.info('participant is in scheme, so forwarding to it...', { fspId })
|
203
|
+
await this.#forwardGetPartiesRequest({
|
204
|
+
sendTo: fspId,
|
205
|
+
headers: GetPartiesService.overrideDestinationHeader(headers, fspId),
|
206
|
+
params
|
207
|
+
})
|
208
|
+
return true
|
209
|
+
}
|
160
210
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
211
|
+
if (this.state.proxyEnabled) {
|
212
|
+
const proxyName = await this.deps.proxyCache.lookupProxyByDfspId(fspId)
|
213
|
+
if (!proxyName) {
|
214
|
+
this.log.warn('no proxyMapping for external DFSP! Deleting reference in oracle...', { fspId })
|
215
|
+
await super.sendDeleteOracleRequest(headers, params)
|
216
|
+
// todo: check if it won't delete all parties
|
217
|
+
return false
|
167
218
|
}
|
168
|
-
|
169
|
-
|
170
|
-
if (
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
219
|
+
|
220
|
+
// Coz there's no destination header, it means we're inside initial inter-scheme discovery phase.
|
221
|
+
// So we should proceed only if source is in scheme (local participant)
|
222
|
+
const isLocalSource = this.isLocalSource()
|
223
|
+
if (isLocalSource) {
|
224
|
+
this.log.info('participant is NOT in scheme, but source is. So forwarding to proxy...', { fspId, proxyName })
|
225
|
+
await this.#forwardGetPartiesRequest({ // todo: add timeout if sendTo is proxy
|
226
|
+
sendTo: proxyName,
|
227
|
+
headers: GetPartiesService.overrideDestinationHeader(headers, fspId),
|
176
228
|
params
|
177
229
|
})
|
230
|
+
return true
|
178
231
|
}
|
232
|
+
}
|
233
|
+
return false
|
234
|
+
}
|
179
235
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
sendTo: proxyName,
|
193
|
-
headers: clonedHeaders,
|
194
|
-
params
|
195
|
-
})
|
196
|
-
}
|
197
|
-
}
|
236
|
+
async #sendPartyNotFoundErrorCallback (headers) {
|
237
|
+
const { params } = this.inputs
|
238
|
+
const callbackHeaders = GetPartiesService.createErrorCallbackHeaders(headers, params)
|
239
|
+
const fspiopError = super.createFspiopIdNotFoundError('No proxy found to start inter-scheme discovery flow')
|
240
|
+
const errorInfo = await this.deps.partiesUtils.makePutPartiesErrorPayload(
|
241
|
+
this.deps.config, fspiopError, callbackHeaders, params
|
242
|
+
)
|
243
|
+
|
244
|
+
await this.sendErrorCallback({
|
245
|
+
errorInfo,
|
246
|
+
headers: callbackHeaders,
|
247
|
+
params
|
198
248
|
})
|
199
|
-
|
200
|
-
log.verbose('processOraclePartyList is done', { sentCount })
|
201
|
-
// todo: think what if sentCount === 0 here
|
249
|
+
return fspiopError
|
202
250
|
}
|
203
251
|
|
204
|
-
async
|
205
|
-
this.
|
206
|
-
|
252
|
+
async #forwardGetPartiesRequest ({ sendTo, headers, params }) {
|
253
|
+
this.stepInProgress('#forwardGetPartiesRequest')
|
254
|
+
const callbackEndpointType = this.deps.partiesUtils.getPartyCbType(params.SubId)
|
255
|
+
const options = this.deps.partiesUtils.partiesRequestOptionsDto(params)
|
256
|
+
|
257
|
+
const sentResult = await this.deps.participant.sendRequest(
|
258
|
+
headers, sendTo, callbackEndpointType, RestMethods.GET, undefined, options, this.deps.childSpan
|
259
|
+
)
|
260
|
+
await this.#setProxyGetPartiesTimeout(sendTo)
|
261
|
+
this.log.debug('#forwardGetPartiesRequest is done:', { sendTo, sentResult })
|
262
|
+
return sentResult
|
263
|
+
}
|
264
|
+
|
265
|
+
async #sendOutProxyRequests ({ proxyNames, alsReq, headers, params }) {
|
266
|
+
this.stepInProgress('#sendOutProxyRequests')
|
267
|
+
const sentList = []
|
268
|
+
let wasLast = false // if any failed proxy request was last
|
269
|
+
|
270
|
+
const sendProxyRequest = (sendTo) => this.#forwardGetPartiesRequest({ sendTo, headers, params })
|
271
|
+
.then(() => { sentList.push(sendTo) })
|
272
|
+
.catch(err => {
|
273
|
+
this.log.error(`error in sending request to proxy ${sendTo}: `, err)
|
274
|
+
this.log.verbose(`removing proxy ${sendTo} from proxyCache...`)
|
275
|
+
return this.deps.proxyCache.receivedErrorResponse(alsReq, sendTo)
|
276
|
+
})
|
277
|
+
.then((isLast) => { wasLast = isLast })
|
278
|
+
.catch(err => {
|
279
|
+
this.log.error(`failed to remove proxy ${sendTo} from proxyCache: `, err)
|
280
|
+
})
|
281
|
+
await Promise.all(proxyNames.map(sendProxyRequest))
|
282
|
+
|
283
|
+
this.log.verbose('#sendOutProxyRequests is done:', { sentList, wasLast, proxyNames })
|
284
|
+
return { sentList, wasLast }
|
285
|
+
}
|
286
|
+
|
287
|
+
async #getFilteredProxyList (proxy) {
|
288
|
+
this.stepInProgress('#getFilteredProxyList')
|
289
|
+
if (!this.state.proxyEnabled) {
|
207
290
|
this.log.warn('proxyCache is not enabled')
|
208
291
|
return []
|
209
292
|
}
|
@@ -213,68 +296,30 @@ class GetPartiesService extends BasePartiesService {
|
|
213
296
|
return proxyNames.filter(name => name !== proxy)
|
214
297
|
}
|
215
298
|
|
216
|
-
async
|
217
|
-
|
218
|
-
this.deps.stepState.inProgress('setSendToProxiesList-10')
|
299
|
+
async #setProxyListToCache (proxyNames, source, params) {
|
300
|
+
this.stepInProgress('#setProxyListToCache')
|
219
301
|
const alsReq = this.deps.partiesUtils.alsRequestDto(source, params)
|
220
|
-
log.info('starting setSendToProxiesList flow: ', { proxyNames, alsReq, proxyCacheTtlSec })
|
221
302
|
|
222
303
|
const isCached = await this.deps.proxyCache.setSendToProxiesList(alsReq, proxyNames, proxyCacheTtlSec)
|
223
304
|
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)
|
305
|
+
throw super.createFspiopIdNotFoundError(ERROR_MESSAGES.failedToCacheSendToProxiesList)
|
243
306
|
}
|
307
|
+
this.log.verbose('#setProxyListToCache is done: ', { alsReq, proxyNames, proxyCacheTtlSec })
|
308
|
+
return alsReq
|
244
309
|
}
|
245
310
|
|
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)
|
311
|
+
async #setProxyGetPartiesTimeout (sendTo) {
|
312
|
+
const isLocalSource = this.isLocalSource()
|
313
|
+
const isSentToProxy = this.state.destination !== sendTo
|
314
|
+
this.log.verbose('isLocalSource and isSentToProxy: ', { isLocalSource, isSentToProxy, sendTo })
|
315
|
+
|
316
|
+
if (isSentToProxy && isLocalSource) {
|
317
|
+
this.stepInProgress('#setProxyGetPartiesTimeout')
|
318
|
+
const alsReq = this.deps.partiesUtils.alsRequestDto(this.state.source, this.inputs.params)
|
319
|
+
const isSet = await this.deps.proxyCache.setProxyGetPartiesTimeout(alsReq, sendTo)
|
320
|
+
this.log.info('#setProxyGetPartiesTimeout is done', { isSet })
|
321
|
+
return isSet
|
322
|
+
}
|
278
323
|
}
|
279
324
|
}
|
280
325
|
|
@@ -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
|
|