@mojaloop/central-ledger 17.7.8 → 17.8.0-orb.1
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/.ncurc.yaml +3 -1
- package/.nvmrc +1 -1
- package/.nycrc.yml +16 -1
- package/Dockerfile +9 -10
- package/README.md +39 -9
- package/audit-ci.jsonc +15 -2
- package/config/default.json +17 -1
- package/docker/central-ledger/default.json +9 -0
- package/docker/config-modifier/configs/central-ledger.js +25 -0
- package/docker/env.sh +15 -0
- package/docker/kafka/scripts/provision.sh +4 -1
- package/docker/ml-api-adapter/default.json +4 -1
- package/docker-compose.yml +90 -2
- package/documentation/db/erd-transfer-timeout.png +0 -0
- package/documentation/db/erd-transfer-timeout.txt +81 -0
- package/documentation/fx-implementation/README.md +48 -0
- package/documentation/fx-implementation/assets/fx-position-movements.drawio.svg +4 -0
- package/documentation/fx-implementation/assets/test-scenario.drawio.svg +4 -0
- package/documentation/sequence-diagrams/Handler - FX timeout.plantuml +123 -0
- package/documentation/sequence-diagrams/Handler - FX timeout.png +0 -0
- package/documentation/sequence-diagrams/Handler - timeout.plantuml +81 -0
- package/documentation/sequence-diagrams/Handler - timeout.png +0 -0
- package/documentation/state-diagrams/transfer-ML-spec-states-diagram.png +0 -0
- package/documentation/state-diagrams/transfer-internal-states-diagram.png +0 -0
- package/documentation/state-diagrams/transfer-internal-states.plantuml +75 -0
- package/documentation/state-diagrams/transfer-states.plantuml +13 -0
- package/migrations/310204_transferParticipant-participantId.js +52 -0
- package/migrations/310403_participantPositionChange-participantCurrencyId.js +47 -0
- package/migrations/310404_participantPositionChange-change.js +46 -0
- package/migrations/600010_fxTransferType.js +43 -0
- package/migrations/600011_fxTransferType-indexes.js +38 -0
- package/migrations/600012_fxParticipantCurrencyType.js +43 -0
- package/migrations/600013_fxParticipantCurrencyType-indexes.js +38 -0
- package/migrations/600100_fxTransferDuplicateCheck.js +42 -0
- package/migrations/600110_fxTransferErrorDuplicateCheck.js.js +17 -0
- package/migrations/600200_fxTransfer.js +51 -0
- package/migrations/600201_fxTransfer-indexes.js +40 -0
- package/migrations/600400_fxTransferStateChange.js +46 -0
- package/migrations/600401_fxTransferStateChange-indexes.js +40 -0
- package/migrations/600501_fxWatchList.js +46 -0
- package/migrations/600502_fxWatchList-indexes.js +40 -0
- package/migrations/600600_fxTransferFulfilmentDuplicateCheck.js +43 -0
- package/migrations/600601_fxTransferFulfilmentDuplicateCheck-indexes.js +38 -0
- package/migrations/600700_fxTransferFulfilment.js +47 -0
- package/migrations/600701_fxTransferFulfilment-indexes.js +43 -0
- package/migrations/600800_fxTransferExtension.js +47 -0
- package/migrations/601400_fxTransferTimeout.js +43 -0
- package/migrations/601401_fxTransferTimeout-indexes.js +37 -0
- package/migrations/601500_fxTransferError.js +44 -0
- package/migrations/601501_fxTransferError-indexes.js +37 -0
- package/migrations/610200_fxTransferParticipant.js +52 -0
- package/migrations/610201_fxTransferParticipant-indexes.js +44 -0
- package/migrations/610202_fxTransferParticipant-participantId.js +52 -0
- package/migrations/610403_participantPositionChange-fxTransfer.js +46 -0
- package/migrations/910101_feature904DataMigration.js +46 -52
- package/migrations/910102_feature949DataMigration.js +219 -225
- package/migrations/950104_settlementModel-settlementAccountTypeId.js +15 -20
- package/migrations/950108_participantProxy.js +18 -0
- package/migrations/950109_fxQuote.js +19 -0
- package/migrations/950110_fxQuoteResponse.js +25 -0
- package/migrations/950111_fxQuoteError.js +23 -0
- package/migrations/950113_fxQuoteDuplicateCheck.js +18 -0
- package/migrations/950114_fxQuoteResponseDuplicateCheck.js +21 -0
- package/migrations/950115_fxQuoteConversionTerms.js +36 -0
- package/migrations/950116_fxQuoteConversionTermsExtension.js +21 -0
- package/migrations/950117_fxQuoteResponseConversionTerms.js +39 -0
- package/migrations/950118_fxQuoteResponseConversionTermsExtension.js +21 -0
- package/migrations/950119_fxCharge.js +27 -0
- package/migrations/960100_create_externalParticipant.js +47 -0
- package/migrations/960110_alter_transferParticipant__addFiled_externalParticipantId.js +50 -0
- package/migrations/960111_alter_fxTransferParticipant__addFiled_externalParticipantId.js +50 -0
- package/package.json +27 -20
- package/seeds/endpointType.js +18 -0
- package/seeds/fxParticipantCurrencyType.js +45 -0
- package/seeds/fxTransferType.js +45 -0
- package/seeds/participant.js +2 -1
- package/seeds/transferParticipantRoleType.js +9 -0
- package/seeds/transferState.js +10 -0
- package/src/api/interface/swagger.json +23 -30
- package/src/api/participants/handler.js +6 -2
- package/src/api/participants/routes.js +8 -7
- package/src/api/root/handler.js +15 -5
- package/src/domain/fx/cyril.js +466 -0
- package/src/domain/fx/index.js +107 -0
- package/src/domain/participant/index.js +108 -1
- package/src/domain/position/abort.js +215 -0
- package/src/domain/position/binProcessor.js +361 -99
- package/src/domain/position/fulfil.js +252 -111
- package/src/domain/position/fx-fulfil.js +138 -0
- package/src/domain/position/fx-prepare.js +280 -0
- package/src/domain/position/fx-timeout-reserved.js +159 -0
- package/src/domain/position/index.js +1 -0
- package/src/domain/position/prepare.js +69 -49
- package/src/domain/position/timeout-reserved.js +162 -0
- package/src/domain/timeout/index.js +26 -2
- package/src/domain/transfer/index.js +22 -5
- package/src/domain/transfer/transform.js +19 -6
- package/src/handlers/admin/handler.js +0 -2
- package/src/handlers/bulk/fulfil/handler.js +5 -5
- package/src/handlers/bulk/get/handler.js +5 -5
- package/src/handlers/bulk/prepare/handler.js +9 -9
- package/src/handlers/bulk/processing/handler.js +8 -7
- package/src/handlers/bulk/shared/validator.js +1 -1
- package/src/handlers/positions/handler.js +23 -10
- package/src/handlers/positions/handlerBatch.js +54 -26
- package/src/handlers/register.js +2 -1
- package/src/handlers/timeouts/handler.js +212 -68
- package/src/handlers/transfers/FxFulfilService.js +387 -0
- package/src/handlers/transfers/createRemittanceEntity.js +106 -0
- package/src/handlers/transfers/dto.js +53 -0
- package/src/handlers/transfers/handler.js +609 -571
- package/src/handlers/transfers/prepare.js +572 -0
- package/src/handlers/transfers/validator.js +75 -14
- package/src/lib/cache.js +1 -1
- package/src/lib/config.js +6 -3
- package/src/lib/healthCheck/subServiceHealth.js +12 -2
- package/src/lib/proxyCache.js +131 -0
- package/src/models/bulkTransfer/facade.js +58 -82
- package/src/models/fxTransfer/duplicateCheck.js +153 -0
- package/src/models/fxTransfer/fxTransfer.js +578 -0
- package/src/models/fxTransfer/fxTransferError.js +53 -0
- package/src/models/fxTransfer/fxTransferExtension.js +41 -0
- package/src/models/fxTransfer/fxTransferTimeout.js +68 -0
- package/src/models/fxTransfer/index.js +15 -0
- package/src/models/fxTransfer/stateChange.js +47 -0
- package/src/models/fxTransfer/watchList.js +49 -0
- package/src/models/ledgerAccountType/ledgerAccountType.js +8 -32
- package/src/models/misc/segment.js +0 -1
- package/src/models/participant/externalParticipant.js +96 -0
- package/src/models/participant/externalParticipantCached.js +148 -0
- package/src/models/participant/facade.js +192 -123
- package/src/models/participant/participant.js +2 -1
- package/src/models/participant/participantCurrency.js +1 -1
- package/src/models/participant/participantPosition.js +2 -8
- package/src/models/position/batch.js +90 -1
- package/src/models/position/facade.js +5 -5
- package/src/models/position/participantPositionChanges.js +68 -0
- package/src/models/settlement/settlementModel.js +5 -23
- package/src/models/transfer/facade.js +806 -447
- package/src/shared/constants.js +52 -0
- package/src/shared/fspiopErrorFactory.js +131 -0
- package/src/shared/logger/index.js +8 -0
- package/src/shared/loggingPlugin.js +43 -0
- package/src/shared/plugins.js +6 -0
- package/src/shared/setup.js +10 -0
- package/test-integration.Dockerfile +1 -1
- package/test.Dockerfile +1 -1
|
@@ -35,20 +35,206 @@ that actually holds the copyright for their contributions (see the
|
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
37
|
const CronJob = require('cron').CronJob
|
|
38
|
-
const Config = require('../../lib/config')
|
|
39
|
-
const TimeoutService = require('../../domain/timeout')
|
|
40
38
|
const Enum = require('@mojaloop/central-services-shared').Enum
|
|
41
|
-
const Kafka = require('@mojaloop/central-services-shared').Util.Kafka
|
|
42
|
-
const Producer = require('@mojaloop/central-services-stream').Util.Producer
|
|
43
39
|
const Utility = require('@mojaloop/central-services-shared').Util
|
|
40
|
+
const Producer = require('@mojaloop/central-services-stream').Util.Producer
|
|
44
41
|
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
|
45
42
|
const EventSdk = require('@mojaloop/event-sdk')
|
|
46
|
-
|
|
47
|
-
const
|
|
43
|
+
|
|
44
|
+
const Config = require('../../lib/config')
|
|
45
|
+
const TimeoutService = require('../../domain/timeout')
|
|
46
|
+
const { logger } = require('../../shared/logger')
|
|
47
|
+
|
|
48
|
+
const { Kafka, resourceVersions } = Utility
|
|
49
|
+
const { Action, Type } = Enum.Events.Event
|
|
50
|
+
|
|
48
51
|
let timeoutJob
|
|
49
52
|
let isRegistered
|
|
50
53
|
let running = false
|
|
51
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Processes timedOut transfers
|
|
57
|
+
*
|
|
58
|
+
* @param {TimedOutTransfer[]} transferTimeoutList
|
|
59
|
+
* @returns {Promise<void>}
|
|
60
|
+
*/
|
|
61
|
+
const _processTimedOutTransfers = async (transferTimeoutList) => {
|
|
62
|
+
const fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.TRANSFER_EXPIRED).toApiErrorObject(Config.ERROR_HANDLING)
|
|
63
|
+
if (!Array.isArray(transferTimeoutList)) {
|
|
64
|
+
transferTimeoutList = [
|
|
65
|
+
{ ...transferTimeoutList }
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
for (const TT of transferTimeoutList) {
|
|
70
|
+
const span = EventSdk.Tracer.createSpan('cl_transfer_timeout')
|
|
71
|
+
try {
|
|
72
|
+
const state = Utility.StreamingProtocol.createEventState(Enum.Events.EventStatus.FAILURE.status, fspiopError.errorInformation.errorCode, fspiopError.errorInformation.errorDescription)
|
|
73
|
+
const metadata = Utility.StreamingProtocol.createMetadataWithCorrelatedEvent(TT.transferId, Enum.Kafka.Topics.NOTIFICATION, Action.TIMEOUT_RECEIVED, state)
|
|
74
|
+
const destination = TT.externalPayerName || TT.payerFsp
|
|
75
|
+
const source = TT.externalPayeeName || TT.payeeFsp
|
|
76
|
+
const headers = Utility.Http.SwitchDefaultHeaders(destination, Enum.Http.HeaderResources.TRANSFERS, Config.HUB_NAME, resourceVersions[Enum.Http.HeaderResources.TRANSFERS].contentVersion)
|
|
77
|
+
const message = Utility.StreamingProtocol.createMessage(TT.transferId, destination, source, metadata, headers, fspiopError, { id: TT.transferId }, `application/vnd.interoperability.${Enum.Http.HeaderResources.TRANSFERS}+json;version=${resourceVersions[Enum.Http.HeaderResources.TRANSFERS].contentVersion}`)
|
|
78
|
+
|
|
79
|
+
span.setTags(Utility.EventFramework.getTransferSpanTags({ payload: message.content.payload, headers }, Type.TRANSFER, Action.TIMEOUT_RECEIVED))
|
|
80
|
+
await span.audit({
|
|
81
|
+
state,
|
|
82
|
+
metadata,
|
|
83
|
+
headers,
|
|
84
|
+
message
|
|
85
|
+
}, EventSdk.AuditEventAction.start)
|
|
86
|
+
|
|
87
|
+
if (TT.bulkTransferId === null) { // regular transfer
|
|
88
|
+
if (TT.transferStateId === Enum.Transfers.TransferInternalState.EXPIRED_PREPARED) {
|
|
89
|
+
message.from = Config.HUB_NAME
|
|
90
|
+
// event & type set above when `const metadata` is initialized to NOTIFICATION / TIMEOUT_RECEIVED
|
|
91
|
+
await Kafka.produceGeneralMessage(
|
|
92
|
+
Config.KAFKA_CONFIG,
|
|
93
|
+
Producer,
|
|
94
|
+
Enum.Kafka.Topics.NOTIFICATION,
|
|
95
|
+
Action.TIMEOUT_RECEIVED,
|
|
96
|
+
message,
|
|
97
|
+
state,
|
|
98
|
+
null,
|
|
99
|
+
span
|
|
100
|
+
)
|
|
101
|
+
} else if (TT.transferStateId === Enum.Transfers.TransferInternalState.RESERVED_TIMEOUT) {
|
|
102
|
+
message.metadata.event.type = Type.POSITION
|
|
103
|
+
message.metadata.event.action = Action.TIMEOUT_RESERVED
|
|
104
|
+
// Key position timeouts with payer account id
|
|
105
|
+
await Kafka.produceGeneralMessage(
|
|
106
|
+
Config.KAFKA_CONFIG,
|
|
107
|
+
Producer,
|
|
108
|
+
Enum.Kafka.Topics.POSITION,
|
|
109
|
+
Action.TIMEOUT_RESERVED,
|
|
110
|
+
message,
|
|
111
|
+
state,
|
|
112
|
+
TT.effectedParticipantCurrencyId?.toString(),
|
|
113
|
+
span,
|
|
114
|
+
Config.KAFKA_CONFIG.EVENT_TYPE_ACTION_TOPIC_MAP?.POSITION?.TIMEOUT_RESERVED
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
} else { // individual transfer from a bulk
|
|
118
|
+
if (TT.transferStateId === Enum.Transfers.TransferInternalState.EXPIRED_PREPARED) {
|
|
119
|
+
message.from = Config.HUB_NAME
|
|
120
|
+
message.metadata.event.type = Type.BULK_PROCESSING
|
|
121
|
+
message.metadata.event.action = Action.BULK_TIMEOUT_RECEIVED
|
|
122
|
+
await Kafka.produceGeneralMessage(
|
|
123
|
+
Config.KAFKA_CONFIG,
|
|
124
|
+
Producer,
|
|
125
|
+
Enum.Kafka.Topics.BULK_PROCESSING,
|
|
126
|
+
Action.BULK_TIMEOUT_RECEIVED,
|
|
127
|
+
message,
|
|
128
|
+
state,
|
|
129
|
+
null,
|
|
130
|
+
span
|
|
131
|
+
)
|
|
132
|
+
} else if (TT.transferStateId === Enum.Transfers.TransferInternalState.RESERVED_TIMEOUT) {
|
|
133
|
+
message.metadata.event.type = Type.POSITION
|
|
134
|
+
message.metadata.event.action = Action.BULK_TIMEOUT_RESERVED
|
|
135
|
+
// Key position timeouts with payer account id
|
|
136
|
+
await Kafka.produceGeneralMessage(
|
|
137
|
+
Config.KAFKA_CONFIG,
|
|
138
|
+
Producer,
|
|
139
|
+
Enum.Kafka.Topics.POSITION,
|
|
140
|
+
Action.BULK_TIMEOUT_RESERVED,
|
|
141
|
+
message,
|
|
142
|
+
state,
|
|
143
|
+
TT.payerParticipantCurrencyId?.toString(),
|
|
144
|
+
span
|
|
145
|
+
)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
} catch (err) {
|
|
149
|
+
logger.error('error in _processTimedOutTransfers:', err)
|
|
150
|
+
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
151
|
+
const state = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, fspiopError.apiErrorCode.code, fspiopError.apiErrorCode.message)
|
|
152
|
+
await span.error(fspiopError, state)
|
|
153
|
+
await span.finish(fspiopError.message, state)
|
|
154
|
+
throw fspiopError
|
|
155
|
+
} finally {
|
|
156
|
+
if (!span.isFinished) {
|
|
157
|
+
await span.finish()
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Processes timedOut fxTransfers
|
|
165
|
+
*
|
|
166
|
+
* @param {TimedOutFxTransfer[]} fxTransferTimeoutList
|
|
167
|
+
* @returns {Promise<void>}
|
|
168
|
+
*/
|
|
169
|
+
const _processFxTimedOutTransfers = async (fxTransferTimeoutList) => {
|
|
170
|
+
const fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.TRANSFER_EXPIRED).toApiErrorObject(Config.ERROR_HANDLING)
|
|
171
|
+
if (!Array.isArray(fxTransferTimeoutList)) {
|
|
172
|
+
fxTransferTimeoutList = [
|
|
173
|
+
{ ...fxTransferTimeoutList }
|
|
174
|
+
]
|
|
175
|
+
}
|
|
176
|
+
for (const fTT of fxTransferTimeoutList) {
|
|
177
|
+
const span = EventSdk.Tracer.createSpan('cl_fx_transfer_timeout')
|
|
178
|
+
try {
|
|
179
|
+
const state = Utility.StreamingProtocol.createEventState(Enum.Events.EventStatus.FAILURE.status, fspiopError.errorInformation.errorCode, fspiopError.errorInformation.errorDescription)
|
|
180
|
+
const metadata = Utility.StreamingProtocol.createMetadataWithCorrelatedEvent(fTT.commitRequestId, Enum.Kafka.Topics.NOTIFICATION, Action.TIMEOUT_RECEIVED, state)
|
|
181
|
+
const destination = fTT.externalInitiatingFspName || fTT.initiatingFsp
|
|
182
|
+
const source = fTT.externalCounterPartyFspName || fTT.counterPartyFsp
|
|
183
|
+
const headers = Utility.Http.SwitchDefaultHeaders(destination, Enum.Http.HeaderResources.FX_TRANSFERS, Config.HUB_NAME, resourceVersions[Enum.Http.HeaderResources.FX_TRANSFERS].contentVersion)
|
|
184
|
+
const message = Utility.StreamingProtocol.createMessage(fTT.commitRequestId, destination, source, metadata, headers, fspiopError, { id: fTT.commitRequestId }, `application/vnd.interoperability.${Enum.Http.HeaderResources.FX_TRANSFERS}+json;version=${resourceVersions[Enum.Http.HeaderResources.FX_TRANSFERS].contentVersion}`)
|
|
185
|
+
|
|
186
|
+
span.setTags(Utility.EventFramework.getTransferSpanTags({ payload: message.content.payload, headers }, Type.FX_TRANSFER, Action.TIMEOUT_RECEIVED))
|
|
187
|
+
await span.audit({
|
|
188
|
+
state,
|
|
189
|
+
metadata,
|
|
190
|
+
headers,
|
|
191
|
+
message
|
|
192
|
+
}, EventSdk.AuditEventAction.start)
|
|
193
|
+
|
|
194
|
+
if (fTT.transferStateId === Enum.Transfers.TransferInternalState.EXPIRED_PREPARED) {
|
|
195
|
+
message.from = Config.HUB_NAME
|
|
196
|
+
// event & type set above when `const metadata` is initialized to NOTIFICATION / TIMEOUT_RECEIVED
|
|
197
|
+
await Kafka.produceGeneralMessage(
|
|
198
|
+
Config.KAFKA_CONFIG,
|
|
199
|
+
Producer,
|
|
200
|
+
Enum.Kafka.Topics.NOTIFICATION,
|
|
201
|
+
Action.FX_TIMEOUT_RESERVED,
|
|
202
|
+
message,
|
|
203
|
+
state,
|
|
204
|
+
null,
|
|
205
|
+
span
|
|
206
|
+
)
|
|
207
|
+
} else if (fTT.transferStateId === Enum.Transfers.TransferInternalState.RESERVED_TIMEOUT) {
|
|
208
|
+
message.metadata.event.type = Type.POSITION
|
|
209
|
+
message.metadata.event.action = Action.FX_TIMEOUT_RESERVED
|
|
210
|
+
// Key position timeouts with payer account id
|
|
211
|
+
await Kafka.produceGeneralMessage(
|
|
212
|
+
Config.KAFKA_CONFIG,
|
|
213
|
+
Producer,
|
|
214
|
+
Enum.Kafka.Topics.POSITION,
|
|
215
|
+
Action.FX_TIMEOUT_RESERVED,
|
|
216
|
+
message,
|
|
217
|
+
state,
|
|
218
|
+
fTT.effectedParticipantCurrencyId?.toString(),
|
|
219
|
+
span,
|
|
220
|
+
Config.KAFKA_CONFIG.EVENT_TYPE_ACTION_TOPIC_MAP?.POSITION?.FX_TIMEOUT_RESERVED
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
} catch (err) {
|
|
224
|
+
logger.error('error in _processFxTimedOutTransfers:', err)
|
|
225
|
+
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
226
|
+
const state = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, fspiopError.apiErrorCode.code, fspiopError.apiErrorCode.message)
|
|
227
|
+
await span.error(fspiopError, state)
|
|
228
|
+
await span.finish(fspiopError.message, state)
|
|
229
|
+
throw fspiopError
|
|
230
|
+
} finally {
|
|
231
|
+
if (!span.isFinished) {
|
|
232
|
+
await span.finish()
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
52
238
|
/**
|
|
53
239
|
* @function TransferTimeoutHandler
|
|
54
240
|
*
|
|
@@ -70,73 +256,31 @@ const timeout = async () => {
|
|
|
70
256
|
const segmentId = timeoutSegment ? timeoutSegment.segmentId : 0
|
|
71
257
|
const cleanup = await TimeoutService.cleanupTransferTimeout()
|
|
72
258
|
const latestTransferStateChange = await TimeoutService.getLatestTransferStateChange()
|
|
259
|
+
|
|
260
|
+
const fxTimeoutSegment = await TimeoutService.getFxTimeoutSegment()
|
|
73
261
|
const intervalMax = (latestTransferStateChange && parseInt(latestTransferStateChange.transferStateChangeId)) || 0
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const headers = Utility.Http.SwitchDefaultHeaders(result[i].payerFsp, Enum.Http.HeaderResources.TRANSFERS, Enum.Http.Headers.FSPIOP.SWITCH.value, resourceVersions[Enum.Http.HeaderResources.TRANSFERS].contentVersion)
|
|
85
|
-
const message = Utility.StreamingProtocol.createMessage(result[i].transferId, result[i].payeeFsp, result[i].payerFsp, metadata, headers, fspiopError, { id: result[i].transferId }, `application/vnd.interoperability.${Enum.Http.HeaderResources.TRANSFERS}+json;version=${resourceVersions[Enum.Http.HeaderResources.TRANSFERS].contentVersion}`)
|
|
86
|
-
span.setTags(Utility.EventFramework.getTransferSpanTags({ payload: message.content.payload, headers }, Enum.Events.Event.Type.TRANSFER, Enum.Events.Event.Action.TIMEOUT_RECEIVED))
|
|
87
|
-
await span.audit({
|
|
88
|
-
state,
|
|
89
|
-
metadata,
|
|
90
|
-
headers,
|
|
91
|
-
message
|
|
92
|
-
}, EventSdk.AuditEventAction.start)
|
|
93
|
-
if (result[i].bulkTransferId === null) { // regular transfer
|
|
94
|
-
if (result[i].transferStateId === Enum.Transfers.TransferInternalState.EXPIRED_PREPARED) {
|
|
95
|
-
message.to = message.from
|
|
96
|
-
message.from = Enum.Http.Headers.FSPIOP.SWITCH.value
|
|
97
|
-
// event & type set above when `const metadata` is initialized to NOTIFICATION / TIMEOUT_RECEIVED
|
|
98
|
-
await Kafka.produceGeneralMessage(Config.KAFKA_CONFIG, Producer, Enum.Kafka.Topics.NOTIFICATION, Enum.Events.Event.Action.TIMEOUT_RECEIVED, message, state, null, span)
|
|
99
|
-
} else if (result[i].transferStateId === Enum.Transfers.TransferInternalState.RESERVED_TIMEOUT) {
|
|
100
|
-
message.metadata.event.type = Enum.Events.Event.Type.POSITION
|
|
101
|
-
message.metadata.event.action = Enum.Events.Event.Action.TIMEOUT_RESERVED
|
|
102
|
-
// Key position timeouts with payer account id
|
|
103
|
-
await Kafka.produceGeneralMessage(Config.KAFKA_CONFIG, Producer, Enum.Kafka.Topics.POSITION, Enum.Events.Event.Action.TIMEOUT_RESERVED, message, state, result[i].payerParticipantCurrencyId?.toString(), span)
|
|
104
|
-
}
|
|
105
|
-
} else { // individual transfer from a bulk
|
|
106
|
-
if (result[i].transferStateId === Enum.Transfers.TransferInternalState.EXPIRED_PREPARED) {
|
|
107
|
-
message.to = message.from
|
|
108
|
-
message.from = Enum.Http.Headers.FSPIOP.SWITCH.value
|
|
109
|
-
message.metadata.event.type = Enum.Events.Event.Type.BULK_PROCESSING
|
|
110
|
-
message.metadata.event.action = Enum.Events.Event.Action.BULK_TIMEOUT_RECEIVED
|
|
111
|
-
await Kafka.produceGeneralMessage(Config.KAFKA_CONFIG, Producer, Enum.Kafka.Topics.BULK_PROCESSING, Enum.Events.Event.Action.BULK_TIMEOUT_RECEIVED, message, state, null, span)
|
|
112
|
-
} else if (result[i].transferStateId === Enum.Transfers.TransferInternalState.RESERVED_TIMEOUT) {
|
|
113
|
-
message.metadata.event.type = Enum.Events.Event.Type.POSITION
|
|
114
|
-
message.metadata.event.action = Enum.Events.Event.Action.BULK_TIMEOUT_RESERVED
|
|
115
|
-
// Key position timeouts with payer account id
|
|
116
|
-
await Kafka.produceGeneralMessage(Config.KAFKA_CONFIG, Producer, Enum.Kafka.Topics.POSITION, Enum.Events.Event.Action.BULK_TIMEOUT_RESERVED, message, state, result[i].payerParticipantCurrencyId?.toString(), span)
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
} catch (err) {
|
|
120
|
-
Logger.isErrorEnabled && Logger.error(err)
|
|
121
|
-
const fspiopError = ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
122
|
-
const state = new EventSdk.EventStateMetadata(EventSdk.EventStatusType.failed, fspiopError.apiErrorCode.code, fspiopError.apiErrorCode.message)
|
|
123
|
-
await span.error(fspiopError, state)
|
|
124
|
-
await span.finish(fspiopError.message, state)
|
|
125
|
-
throw fspiopError
|
|
126
|
-
} finally {
|
|
127
|
-
if (!span.isFinished) {
|
|
128
|
-
await span.finish()
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
262
|
+
const fxIntervalMin = fxTimeoutSegment ? fxTimeoutSegment.value : 0
|
|
263
|
+
const fxSegmentId = fxTimeoutSegment ? fxTimeoutSegment.segmentId : 0
|
|
264
|
+
const fxCleanup = await TimeoutService.cleanupFxTransferTimeout()
|
|
265
|
+
const latestFxTransferStateChange = await TimeoutService.getLatestFxTransferStateChange()
|
|
266
|
+
const fxIntervalMax = (latestFxTransferStateChange && parseInt(latestFxTransferStateChange.fxTransferStateChangeId)) || 0
|
|
267
|
+
|
|
268
|
+
const { transferTimeoutList, fxTransferTimeoutList } = await TimeoutService.timeoutExpireReserved(segmentId, intervalMin, intervalMax, fxSegmentId, fxIntervalMin, fxIntervalMax)
|
|
269
|
+
transferTimeoutList && await _processTimedOutTransfers(transferTimeoutList)
|
|
270
|
+
fxTransferTimeoutList && await _processFxTimedOutTransfers(fxTransferTimeoutList)
|
|
271
|
+
|
|
132
272
|
return {
|
|
133
273
|
intervalMin,
|
|
134
274
|
cleanup,
|
|
135
275
|
intervalMax,
|
|
136
|
-
|
|
276
|
+
fxIntervalMin,
|
|
277
|
+
fxCleanup,
|
|
278
|
+
fxIntervalMax,
|
|
279
|
+
transferTimeoutList,
|
|
280
|
+
fxTransferTimeoutList
|
|
137
281
|
}
|
|
138
282
|
} catch (err) {
|
|
139
|
-
|
|
283
|
+
logger.error('error in timeout:', err)
|
|
140
284
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
141
285
|
} finally {
|
|
142
286
|
running = false
|
|
@@ -192,7 +336,7 @@ const registerTimeoutHandler = async () => {
|
|
|
192
336
|
await timeoutJob.start()
|
|
193
337
|
return true
|
|
194
338
|
} catch (err) {
|
|
195
|
-
|
|
339
|
+
logger.error('error in registerTimeoutHandler:', err)
|
|
196
340
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
197
341
|
}
|
|
198
342
|
}
|
|
@@ -212,7 +356,7 @@ const registerAllHandlers = async () => {
|
|
|
212
356
|
}
|
|
213
357
|
return true
|
|
214
358
|
} catch (err) {
|
|
215
|
-
|
|
359
|
+
logger.error('error in registerAllHandlers:', err)
|
|
216
360
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
217
361
|
}
|
|
218
362
|
}
|