@mojaloop/central-ledger 9.2.2 → 15.1.3-snapshot.2
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/.circleci/config.yml +625 -204
- package/.env +3 -2
- package/.ncurc.yaml +9 -0
- package/.nvmrc +1 -1
- package/.versionrc +15 -0
- package/CHANGELOG.md +353 -0
- package/CODEOWNERS +31 -0
- package/Dockerfile +20 -14
- package/LICENSE.md +4 -4
- package/Onboarding.md +0 -7
- package/README.md +99 -22
- package/audit-resolve.json +136 -1
- package/config/default.json +82 -27
- package/docker/central-ledger/default.json +68 -21
- package/docker/ml-api-adapter/default.json +10 -1
- package/docker/wait-for/wait-for-objstore.sh +1 -6
- package/docker/wait-for/wait-for.env +1 -1
- package/docker-compose.integration.yml +8 -5
- package/docker-compose.yml +73 -16
- package/migrations/310203_transferParticipant-indexes.js +38 -0
- package/migrations/310503_participantLimit-indexes-composite.js +38 -0
- package/migrations/{400401_settlementWindowStateChange-indexes.js → 400401_settlmentWindowStateChange-indexes.js} +0 -0
- package/migrations/401301_settlementModel-indexes.js +2 -0
- package/migrations/500401_quote-hotfix-2719.js +58 -0
- package/migrations/500501_feature-fixSubIdRef.js +53 -0
- package/migrations/500601_party-2480.js +63 -0
- package/migrations/501001_quoteExtension-quote-service-174.js +46 -0
- package/migrations/501002_quoteExtension-2522.js +61 -0
- package/migrations/800101_feature-fixSubIdRef.js +90 -0
- package/migrations/910102_hotfix954.js +4 -1
- package/migrations/940100_quotePartyIdInfoExtension.js +52 -0
- package/migrations/940101_quotePartyIdInfoExtension-2522.js +64 -0
- package/migrations/950100_settlementContentAggregation-decimal184.js +40 -0
- package/migrations/950101_transferParticipantStateChange.js +46 -0
- package/migrations/950102_settlementModel-adjustPosition.js +42 -0
- package/migrations/950103_dropTransferParticipantStateChange.js +47 -0
- package/migrations/950104_settlementModel-settlementAccountTypeId.js +79 -0
- package/migrations/950106_unique_settlement_model_ledger_account_currency.js +38 -0
- package/migrations/950107_settlementWindowContent_foreign_settlementModel.js +60 -0
- package/package.json +99 -81
- package/scripts/_wait4_all.js +146 -0
- package/seeds/amountType.js +4 -6
- package/seeds/balanceOfPayments.js +4 -6
- package/seeds/bulkProcessingState.js +4 -6
- package/seeds/bulkTransferState.js +4 -6
- package/seeds/currency.js +4 -6
- package/seeds/endpointType.js +128 -7
- package/seeds/ledgerAccountType.js +11 -10
- package/seeds/ledgerEntryType.js +5 -7
- package/seeds/participant.js +4 -6
- package/seeds/participantLimitType.js +4 -6
- package/seeds/partyIdentifierType.js +4 -6
- package/seeds/partyType.js +4 -6
- package/seeds/settlementDelay.js +4 -6
- package/seeds/settlementGranularity.js +4 -6
- package/seeds/settlementInterchange.js +4 -6
- package/seeds/settlementState.js +4 -6
- package/seeds/settlementWindow1State.js +4 -6
- package/seeds/transactionInitiator.js +4 -6
- package/seeds/transactionInitiatorType.js +4 -6
- package/seeds/transactionScenario.js +4 -6
- package/seeds/transferParticipantRoleType.js +4 -6
- package/seeds/transferState.js +9 -6
- package/src/api/interface/swagger.json +728 -948
- package/src/api/ledgerAccountTypes/handler.js +55 -0
- package/src/api/ledgerAccountTypes/routes.js +63 -0
- package/src/api/metrics/handler.js +2 -2
- package/src/api/metrics/routes.js +1 -1
- package/src/api/participants/handler.js +43 -35
- package/src/api/participants/routes.js +13 -13
- package/src/api/root/routes.js +2 -2
- package/src/api/settlementModels/handler.js +9 -26
- package/src/api/settlementModels/routes.js +4 -4
- package/src/api/transactions/handler.js +46 -0
- package/src/api/transactions/routes.js +45 -0
- package/src/domain/bulkTransfer/index.js +6 -5
- package/src/domain/ledgerAccountTypes/index.js +58 -0
- package/src/domain/participant/index.js +55 -4
- package/src/domain/position/index.js +18 -2
- package/src/domain/settlement/index.js +39 -6
- package/src/domain/transactions/index.js +61 -0
- package/src/domain/transfer/index.js +22 -2
- package/src/domain/transfer/transform.js +3 -3
- package/src/handlers/admin/handler.js +24 -32
- package/src/handlers/bulk/fulfil/handler.js +89 -56
- package/src/handlers/bulk/get/handler.js +203 -0
- package/src/handlers/bulk/index.js +4 -1
- package/src/handlers/bulk/prepare/handler.js +30 -29
- package/src/handlers/bulk/processing/handler.js +61 -32
- package/src/handlers/bulk/shared/validator.js +13 -1
- package/src/handlers/index.js +18 -9
- package/src/handlers/positions/handler.js +67 -46
- package/src/handlers/register.js +7 -7
- package/src/handlers/timeouts/handler.js +9 -4
- package/src/handlers/transfers/handler.js +408 -182
- package/src/handlers/transfers/validator.js +41 -11
- package/src/lib/cache.js +8 -34
- package/src/lib/config.js +5 -7
- package/src/lib/enum.js +22 -22
- package/src/lib/enumCached.js +76 -0
- package/src/lib/healthCheck/subServiceHealth.js +2 -2
- package/src/lib/requestLogger.js +9 -9
- package/src/lib/urlParser.js +1 -1
- package/src/models/bulkTransfer/bulkTransfer.js +6 -6
- package/src/models/bulkTransfer/bulkTransferAssociation.js +3 -3
- package/src/models/bulkTransfer/bulkTransferDuplicateCheck.js +4 -4
- package/src/models/bulkTransfer/bulkTransferExtension.js +2 -2
- package/src/models/bulkTransfer/bulkTransferFulfilmentDuplicateCheck.js +4 -4
- package/src/models/bulkTransfer/bulkTransferStateChange.js +7 -7
- package/src/models/bulkTransfer/facade.js +54 -3
- package/src/models/bulkTransfer/individualTransfer.js +2 -2
- package/src/models/ilpPackets/ilpPacket.js +36 -0
- package/src/models/ledgerAccountType/ledgerAccountType.js +139 -3
- package/src/models/misc/migrationLock.js +1 -1
- package/src/models/misc/segment.js +1 -1
- package/src/models/participant/facade.js +226 -76
- package/src/models/participant/participant.js +6 -5
- package/src/models/participant/participantCached.js +8 -0
- package/src/models/participant/participantCurrency.js +7 -7
- package/src/models/participant/participantCurrencyCached.js +11 -1
- package/src/models/participant/participantLimit.js +13 -13
- package/src/models/participant/participantLimitCached.js +124 -0
- package/src/models/participant/participantPosition.js +34 -5
- package/src/models/participant/participantPositionChange.js +10 -2
- package/src/models/position/facade.js +112 -18
- package/src/models/position/participantPosition.js +6 -6
- package/src/models/settlement/settlementModel.js +92 -17
- package/src/models/settlement/settlementModelCached.js +139 -0
- package/src/models/transfer/facade.js +97 -32
- package/src/models/transfer/ilpPacket.js +4 -4
- package/src/models/transfer/transfer.js +7 -7
- package/src/models/transfer/transferDuplicateCheck.js +21 -5
- package/src/models/transfer/transferError.js +5 -5
- package/src/models/transfer/transferErrorDuplicateCheck.js +4 -4
- package/src/models/transfer/transferExtension.js +4 -4
- package/src/models/transfer/transferFulfilment.js +5 -5
- package/src/models/transfer/transferFulfilmentDuplicateCheck.js +4 -4
- package/src/models/transfer/transferParticipant.js +3 -3
- package/src/models/transfer/transferStateChange.js +11 -11
- package/src/models/transfer/transferTimeout.js +5 -5
- package/src/schema/bulkTransfer.js +4 -4
- package/src/shared/plugins.js +10 -9
- package/src/shared/setup.js +69 -46
- package/test/integration/domain/participant/index.test.js +2 -0
- package/test/integration/handlers/handlers.test.js +605 -166
- package/test/integration/handlers/root.test.js +1 -1
- package/test/integration/helpers/hubAccounts.js +62 -0
- package/test/integration/helpers/ilpPacket.js +1 -1
- package/test/integration/helpers/participantFundsInOut.js +80 -0
- package/test/integration/helpers/participantLimit.js +6 -1
- package/test/integration/helpers/settlementModels.js +88 -0
- package/test/integration/helpers/testConsumer.js +163 -0
- package/test/integration/helpers/testProducer.js +0 -1
- package/test/integration/helpers/transferDuplicateCheck.js +1 -1
- package/test/integration/helpers/transferStateChange.js +1 -1
- package/test/integration/helpers/transferTestHelper.js +3 -5
- package/test/integration/models/transfer/transferStateChange.test.js +6 -0
- package/test/unit/api/ledgerAccountTypes/handler.test.js +126 -0
- package/test/unit/api/ledgerAccountTypes/routes.test.js +52 -0
- package/test/unit/api/participants/handler.test.js +75 -33
- package/test/unit/api/root/handler.test.js +1 -1
- package/test/unit/api/root/routes.test.js +2 -2
- package/test/unit/api/settlementModels/handler.test.js +21 -57
- package/test/unit/api/transactions/handler.test.js +108 -0
- package/test/unit/api/transactions/routes.test.js +38 -0
- package/test/unit/domain/ledgerAccountTypes/index.test.js +197 -0
- package/test/unit/domain/participant/index.test.js +115 -2
- package/test/unit/domain/settlement/index.test.js +199 -29
- package/test/unit/domain/transactions/index.test.js +128 -0
- package/test/unit/domain/transfer/index.test.js +1 -0
- package/test/unit/domain/transfer/transform.test.js +2 -0
- package/test/unit/handlers/admin/handler.test.js +5 -5
- package/test/unit/handlers/bulk/get/handler.test.js +401 -0
- package/test/unit/handlers/index.test.js +6 -0
- package/test/unit/handlers/positions/handler.test.js +26 -0
- package/test/unit/handlers/register.test.js +2 -0
- package/test/unit/handlers/transfers/handler.test.js +491 -36
- package/test/unit/handlers/transfers/validator.test.js +31 -31
- package/test/unit/lib/cache.test.js +0 -64
- package/test/unit/lib/cachingOfEnums.test.js +121 -0
- package/test/unit/lib/config.test.js +34 -0
- package/test/unit/lib/enum.test.js +6 -1
- package/test/unit/lib/enumCached.test.js +82 -0
- package/test/unit/lib/healthCheck/subServiceHealth.test.js +2 -0
- package/test/unit/lib/requestLogger.test.js +14 -12
- package/test/unit/models/ilpPackets/ilpPacket.test.js +89 -0
- package/test/unit/models/ledgerAccountType/ledgerAccountType.test.js +255 -6
- package/test/unit/models/misc/migrationLock.test.js +4 -0
- package/test/unit/models/misc/segment.test.js +5 -0
- package/test/unit/models/participant/facade.test.js +493 -54
- package/test/unit/models/participant/participant.test.js +4 -0
- package/test/unit/models/participant/participantCurrency.test.js +22 -9
- package/test/unit/models/participant/participantCurrencyCached.test.js +1 -1
- package/test/unit/models/participant/participantLimit.test.js +97 -0
- package/test/unit/models/participant/participantLimitCached.test.js +232 -0
- package/test/unit/models/participant/participantPosition.test.js +217 -0
- package/test/unit/models/participant/participantPositionChange.test.js +3 -0
- package/test/unit/models/position/facade.test.js +318 -29
- package/test/unit/models/position/participantPosition.test.js +22 -7
- package/test/unit/models/settlement/settlementModel.test.js +18 -37
- package/test/unit/models/settlement/settlementModelCached.test.js +171 -0
- package/test/unit/models/transfer/facade.test.js +115 -0
- package/test/unit/models/transfer/ilpPacket.test.js +28 -11
- package/test/unit/models/transfer/transfer.test.js +13 -4
- package/test/unit/models/transfer/transferDuplicateCheck.test.js +4 -0
- package/test/unit/models/transfer/transferError.test.js +5 -1
- package/test/unit/models/transfer/transferErrorDuplicateCheck.test.js +4 -0
- package/test/unit/models/transfer/transferExtension.test.js +26 -9
- package/test/unit/models/transfer/transferFulfilment.test.js +14 -5
- package/test/unit/models/transfer/transferFulfilmentDuplicateCheck.test.js +4 -0
- package/test/unit/models/transfer/transferParticipant.test.js +14 -5
- package/test/unit/models/transfer/transferStateChange.test.js +3 -0
- package/test/unit/models/transfer/transferTimeout.test.js +6 -0
- package/test/unit/seeds/amountType.test.js +6 -22
- package/test/unit/seeds/balanceOfPayments.test.js +6 -22
- package/test/unit/seeds/bulkProcessingState.test.js +84 -0
- package/test/unit/{lib/sidecar/nullClient.test.js → seeds/bulkTransferState.test.js} +36 -39
- package/test/unit/seeds/currency.test.js +6 -22
- package/test/unit/seeds/endpointType.test.js +6 -22
- package/test/unit/seeds/ledgerAccountType.test.js +5 -22
- package/test/unit/seeds/ledgerEntryType.test.js +6 -22
- package/test/unit/seeds/participant.test.js +5 -22
- package/test/unit/seeds/participantLimitType.test.js +6 -22
- package/test/unit/seeds/partyIdentifierType.test.js +6 -22
- package/test/unit/seeds/partyType.test.js +6 -22
- package/test/unit/seeds/settlementState.test.js +5 -22
- package/test/unit/seeds/settlementWindow1State.test.js +5 -22
- package/test/unit/seeds/transactionInitiator.test.js +6 -22
- package/test/unit/seeds/transactionInitiatorType.test.js +6 -22
- package/test/unit/seeds/transactionScenario.test.js +6 -22
- package/test/unit/seeds/transferParticipantRoleType.test.js +6 -22
- package/test/unit/seeds/transferState.test.js +6 -22
- package/test/unit/shared/plugins.test.js +31 -1
- package/test/unit/shared/setup.test.js +25 -36
- package/test/util/helpers.js +37 -2
- package/test/util/randomTransfers.js +1 -1
- package/test/util/scripts/env.sh +6 -5
- package/test/util/scripts/populateTestData.sh +204 -181
- package/test/util/scripts/populateTestDataForLegacySimulator.sh +261 -0
- package/test/util/scripts/restartObjStore.sh +1 -1
- package/test-integration.Dockerfile +15 -15
- package/test.Dockerfile +12 -12
- package/.circleci/_set_up_deploy_envs.sh +0 -47
- package/.dockerignore +0 -17
- package/.ncurc.json +0 -3
- package/server.sh +0 -4
- package/sonar-project.properties +0 -17
- package/src/lib/sidecar/index.js +0 -47
- package/src/lib/sidecar/nullClient.js +0 -18
- package/test/.env +0 -8
- package/test/integration-config.json +0 -367
- package/test/integration-runner.env +0 -31
- package/test/integration-runner.sh +0 -264
- package/test/spec-runner.sh +0 -132
- package/test/unit/lib/sidecar/index.test.js +0 -148
- package/test/unit/models/position/participantLimit.test.js +0 -135
|
@@ -34,27 +34,27 @@ const Logger = require('@mojaloop/central-services-logger')
|
|
|
34
34
|
|
|
35
35
|
const insert = async (participantLimit) => {
|
|
36
36
|
try {
|
|
37
|
-
return await Db.participantLimit.insert(participantLimit)
|
|
37
|
+
return await Db.from('participantLimit').insert(participantLimit)
|
|
38
38
|
} catch (err) {
|
|
39
|
-
Logger.error(err)
|
|
39
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
40
40
|
throw err
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
const update = async (participantLimit) => {
|
|
45
45
|
try {
|
|
46
|
-
return await Db.participantLimit.update({ participantCurrencyId: participantLimit.participantCurrencyId }, { value: participantLimit.value, isActive: participantLimit.isActive })
|
|
46
|
+
return await Db.from('participantLimit').update({ participantCurrencyId: participantLimit.participantCurrencyId }, { value: participantLimit.value, isActive: participantLimit.isActive })
|
|
47
47
|
} catch (err) {
|
|
48
|
-
Logger.error(err)
|
|
48
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
49
49
|
throw err
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
const
|
|
53
|
+
const getAll = async () => {
|
|
54
54
|
try {
|
|
55
|
-
return await Db.participantLimit.
|
|
55
|
+
return await Db.from('participantLimit').find({})
|
|
56
56
|
} catch (err) {
|
|
57
|
-
Logger.error(err)
|
|
57
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
58
58
|
throw err
|
|
59
59
|
}
|
|
60
60
|
}
|
|
@@ -73,9 +73,9 @@ const getLimitByCurrencyId = async (participantCurrencyId) => {
|
|
|
73
73
|
|
|
74
74
|
const getByParticipantCurrencyId = async (participantCurrencyId) => {
|
|
75
75
|
try {
|
|
76
|
-
return Db.participantLimit.findOne({ participantCurrencyId, isActive: 1 })
|
|
76
|
+
return Db.from('participantLimit').findOne({ participantCurrencyId, isActive: 1 })
|
|
77
77
|
} catch (err) {
|
|
78
|
-
Logger.error(err)
|
|
78
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
79
79
|
throw err
|
|
80
80
|
}
|
|
81
81
|
}
|
|
@@ -94,9 +94,9 @@ const getByParticipantCurrencyId = async (participantCurrencyId) => {
|
|
|
94
94
|
|
|
95
95
|
const destroyByParticipantCurrencyId = async (participantCurrencyId) => {
|
|
96
96
|
try {
|
|
97
|
-
return Db.participantLimit.destroy({ participantCurrencyId })
|
|
97
|
+
return Db.from('participantLimit').destroy({ participantCurrencyId })
|
|
98
98
|
} catch (err) {
|
|
99
|
-
Logger.error(err)
|
|
99
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
100
100
|
throw err
|
|
101
101
|
}
|
|
102
102
|
}
|
|
@@ -121,7 +121,7 @@ const destroyByParticipantId = async (participantId) => {
|
|
|
121
121
|
.whereIn('participantCurrencyId', participantCurrencyIdList)
|
|
122
122
|
.del()
|
|
123
123
|
} catch (err) {
|
|
124
|
-
Logger.error(err)
|
|
124
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
125
125
|
throw err
|
|
126
126
|
}
|
|
127
127
|
}
|
|
@@ -129,8 +129,8 @@ const destroyByParticipantId = async (participantId) => {
|
|
|
129
129
|
module.exports = {
|
|
130
130
|
insert,
|
|
131
131
|
update,
|
|
132
|
-
getLimitByCurrencyId,
|
|
133
132
|
getByParticipantCurrencyId,
|
|
133
|
+
getAll,
|
|
134
134
|
destroyByParticipantCurrencyId,
|
|
135
135
|
destroyByParticipantId
|
|
136
136
|
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/*****
|
|
2
|
+
License
|
|
3
|
+
--------------
|
|
4
|
+
Copyright © 2017 Bill & Melinda Gates Foundation
|
|
5
|
+
The Mojaloop files are made available by the Bill & Melinda Gates Foundation under the Apache License, Version 2.0 (the "License") and you may not use these files except in compliance with the License. You may obtain a copy of the License at
|
|
6
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
7
|
+
Unless required by applicable law or agreed to in writing, the Mojaloop files are distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
|
8
|
+
Contributors
|
|
9
|
+
--------------
|
|
10
|
+
This is the official list of the Mojaloop project contributors for this file.
|
|
11
|
+
Names of the original copyright holders (individuals or organizations)
|
|
12
|
+
should be listed with a '*' in the first column. People who have
|
|
13
|
+
contributed from an organization can be listed under the organization
|
|
14
|
+
that actually holds the copyright for their contributions (see the
|
|
15
|
+
Gates Foundation organization for an example). Those individuals should have
|
|
16
|
+
their names indented and be marked with a '-'. Email address can be added
|
|
17
|
+
optionally within square brackets <email>.
|
|
18
|
+
* Gates Foundation
|
|
19
|
+
- Name Surname <name.surname@gatesfoundation.com>
|
|
20
|
+
|
|
21
|
+
* Roman Pietrzak <roman.pietrzak@modusbox.com>
|
|
22
|
+
--------------
|
|
23
|
+
******/
|
|
24
|
+
|
|
25
|
+
'use strict'
|
|
26
|
+
|
|
27
|
+
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
|
28
|
+
const Cache = require('../../lib/cache')
|
|
29
|
+
const ParticipantLimitModel = require('../../models/participant/participantLimit')
|
|
30
|
+
const Metrics = require('@mojaloop/central-services-metrics')
|
|
31
|
+
|
|
32
|
+
let cacheClient
|
|
33
|
+
let participantLimitAllCacheKey
|
|
34
|
+
|
|
35
|
+
/*
|
|
36
|
+
Private API
|
|
37
|
+
*/
|
|
38
|
+
const buildUnifiedParticipantsLimitData = (allLimitParticipants) => {
|
|
39
|
+
// build indexes (or indices?) - optimization for byId and byName access
|
|
40
|
+
const indexByParticipantCurrencyId = {}
|
|
41
|
+
|
|
42
|
+
allLimitParticipants.forEach((oneLimitParticipant) => {
|
|
43
|
+
// LimitParticipant API returns Date type, but cache internals will serialize it to String
|
|
44
|
+
// by calling JSON.stringify(), which calls .toISOString() on a Date object.
|
|
45
|
+
// Let's ensure all places return same kind of String.
|
|
46
|
+
oneLimitParticipant.createdDate = JSON.stringify(oneLimitParticipant.createdDate)
|
|
47
|
+
|
|
48
|
+
// Add to indexes
|
|
49
|
+
indexByParticipantCurrencyId[oneLimitParticipant.participantCurrencyId] = oneLimitParticipant
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
// build unified structure - indexes + data
|
|
53
|
+
const unifiedLimitParticipants = {
|
|
54
|
+
indexByParticipantCurrencyId,
|
|
55
|
+
allLimitParticipants
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return unifiedLimitParticipants
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const getParticipantLimitCached = async () => {
|
|
62
|
+
const histTimer = Metrics.getHistogram(
|
|
63
|
+
'model_participant',
|
|
64
|
+
'model_getParticipantLimitCached - Metrics for participant model',
|
|
65
|
+
['success', 'queryName', 'hit']
|
|
66
|
+
).startTimer()
|
|
67
|
+
// Do we have valid participantsLimit list in the cache ?
|
|
68
|
+
let cachedLimitParticipants = cacheClient.get(participantLimitAllCacheKey)
|
|
69
|
+
if (!cachedLimitParticipants) {
|
|
70
|
+
// No participantsLimit in the cache, so fetch from participantsLimit API
|
|
71
|
+
const allLimitParticipants = await ParticipantLimitModel.getAll()
|
|
72
|
+
cachedLimitParticipants = buildUnifiedParticipantsLimitData(allLimitParticipants)
|
|
73
|
+
|
|
74
|
+
// store in cache
|
|
75
|
+
cacheClient.set(participantLimitAllCacheKey, cachedLimitParticipants)
|
|
76
|
+
histTimer({ success: true, queryName: 'model_getParticipantLimitCached', hit: false })
|
|
77
|
+
} else {
|
|
78
|
+
// unwrap participants list from catbox structure
|
|
79
|
+
cachedLimitParticipants = cachedLimitParticipants.item
|
|
80
|
+
histTimer({ success: true, queryName: 'model_getParticipantLimitCached', hit: true })
|
|
81
|
+
}
|
|
82
|
+
return cachedLimitParticipants
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/*
|
|
86
|
+
Public API
|
|
87
|
+
*/
|
|
88
|
+
exports.initialize = async () => {
|
|
89
|
+
/* Register as cache client */
|
|
90
|
+
const participantLimitCacheClientMeta = {
|
|
91
|
+
id: 'participantLimit',
|
|
92
|
+
preloadCache: getParticipantLimitCached
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
cacheClient = Cache.registerCacheClient(participantLimitCacheClientMeta)
|
|
96
|
+
participantLimitAllCacheKey = cacheClient.createKey('all')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
exports.invalidateParticipantLimitCache = async () => {
|
|
100
|
+
cacheClient.drop(participantLimitAllCacheKey)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
exports.getByParticipantCurrencyId = async (id) => {
|
|
104
|
+
const cachedLimitParticipants = await getParticipantLimitCached()
|
|
105
|
+
const participantLimitById = cachedLimitParticipants.indexByParticipantCurrencyId[id]
|
|
106
|
+
return participantLimitById
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const withInvalidate = (theFunctionName) => {
|
|
110
|
+
return async (...args) => {
|
|
111
|
+
try {
|
|
112
|
+
const result = await ParticipantLimitModel[theFunctionName](...args)
|
|
113
|
+
await exports.invalidateParticipantLimitCache()
|
|
114
|
+
return result
|
|
115
|
+
} catch (err) {
|
|
116
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
exports.insert = withInvalidate('insert')
|
|
122
|
+
exports.update = withInvalidate('update')
|
|
123
|
+
exports.destroyByParticipantCurrencyId = withInvalidate('destroyByParticipantCurrencyId')
|
|
124
|
+
exports.destroyByParticipantId = withInvalidate('destroyByParticipantId')
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
const Db = require('../../lib/db')
|
|
36
36
|
const ParticipantCurrencyModel = require('./participantCurrencyCached')
|
|
37
37
|
const Logger = require('@mojaloop/central-services-logger')
|
|
38
|
+
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
|
38
39
|
|
|
39
40
|
/**
|
|
40
41
|
* @function GetByParticipantCurrencyId
|
|
@@ -50,9 +51,9 @@ const Logger = require('@mojaloop/central-services-logger')
|
|
|
50
51
|
|
|
51
52
|
const getByParticipantCurrencyId = async (participantCurrencyId) => {
|
|
52
53
|
try {
|
|
53
|
-
return Db.participantPosition.findOne({ participantCurrencyId })
|
|
54
|
+
return Db.from('participantPosition').findOne({ participantCurrencyId })
|
|
54
55
|
} catch (err) {
|
|
55
|
-
Logger.error(err)
|
|
56
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
56
57
|
throw err
|
|
57
58
|
}
|
|
58
59
|
}
|
|
@@ -71,9 +72,9 @@ const getByParticipantCurrencyId = async (participantCurrencyId) => {
|
|
|
71
72
|
|
|
72
73
|
const destroyByParticipantCurrencyId = async (participantCurrencyId) => {
|
|
73
74
|
try {
|
|
74
|
-
return Db.participantPosition.destroy({ participantCurrencyId })
|
|
75
|
+
return Db.from('participantPosition').destroy({ participantCurrencyId })
|
|
75
76
|
} catch (err) {
|
|
76
|
-
Logger.error(err)
|
|
77
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
77
78
|
throw err
|
|
78
79
|
}
|
|
79
80
|
}
|
|
@@ -98,12 +99,40 @@ const destroyByParticipantId = async (participantId) => {
|
|
|
98
99
|
.whereIn('participantCurrencyId', participantCurrencyIdList)
|
|
99
100
|
.del()
|
|
100
101
|
} catch (err) {
|
|
101
|
-
Logger.error(err)
|
|
102
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
102
103
|
throw err
|
|
103
104
|
}
|
|
104
105
|
}
|
|
105
106
|
|
|
107
|
+
const createParticipantPositionRecords = async (participantPositions, trx) => {
|
|
108
|
+
try {
|
|
109
|
+
const knex = Db.getKnex()
|
|
110
|
+
const trxFunction = async (trx, doCommit = true) => {
|
|
111
|
+
try {
|
|
112
|
+
await knex
|
|
113
|
+
.batchInsert('participantPosition', participantPositions)
|
|
114
|
+
.transacting(trx)
|
|
115
|
+
if (doCommit) {
|
|
116
|
+
await trx.commit
|
|
117
|
+
}
|
|
118
|
+
} catch (err) {
|
|
119
|
+
if (doCommit) {
|
|
120
|
+
await trx.rollback
|
|
121
|
+
}
|
|
122
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (trx) {
|
|
126
|
+
return trxFunction(trx, false)
|
|
127
|
+
} else {
|
|
128
|
+
return knex.transaction(trxFunction)
|
|
129
|
+
}
|
|
130
|
+
} catch (err) {
|
|
131
|
+
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
106
134
|
module.exports = {
|
|
135
|
+
createParticipantPositionRecords,
|
|
107
136
|
getByParticipantCurrencyId,
|
|
108
137
|
destroyByParticipantCurrencyId,
|
|
109
138
|
destroyByParticipantId
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
const Db = require('../../lib/db')
|
|
32
32
|
const Logger = require('@mojaloop/central-services-logger')
|
|
33
|
+
const Metrics = require('@mojaloop/central-services-metrics')
|
|
33
34
|
|
|
34
35
|
/**
|
|
35
36
|
* @function getByParticipantPositionId
|
|
@@ -44,17 +45,24 @@ const Logger = require('@mojaloop/central-services-logger')
|
|
|
44
45
|
*/
|
|
45
46
|
|
|
46
47
|
const getByParticipantPositionId = async (participantPositionId) => {
|
|
48
|
+
const histTimer = Metrics.getHistogram(
|
|
49
|
+
'model_participant',
|
|
50
|
+
'model_getByParticipantPositionId - Metrics for participant model',
|
|
51
|
+
['success', 'queryName', 'hit']
|
|
52
|
+
).startTimer()
|
|
47
53
|
try {
|
|
48
|
-
return await Db.participantPositionChange.query(async (builder) => {
|
|
54
|
+
return await Db.from('participantPositionChange').query(async (builder) => {
|
|
49
55
|
const result = builder
|
|
50
56
|
.where({ 'participantPositionChange.participantPositionId': participantPositionId })
|
|
51
57
|
.select('participantPositionChange.*')
|
|
52
58
|
.orderBy('participantPositionChangeId', 'desc')
|
|
53
59
|
.first()
|
|
60
|
+
histTimer({ success: true, queryName: 'model_getByParticipantPositionId', hit: false })
|
|
54
61
|
return result
|
|
55
62
|
})
|
|
56
63
|
} catch (err) {
|
|
57
|
-
Logger.error(err)
|
|
64
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
65
|
+
histTimer({ success: false, queryName: 'model_getByParticipantPositionId', hit: false })
|
|
58
66
|
throw err
|
|
59
67
|
}
|
|
60
68
|
}
|
|
@@ -33,18 +33,36 @@
|
|
|
33
33
|
const Db = require('../../lib/db')
|
|
34
34
|
const Enum = require('@mojaloop/central-services-shared').Enum
|
|
35
35
|
const participantFacade = require('../participant/facade')
|
|
36
|
+
const SettlementModelCached = require('../../models/settlement/settlementModelCached')
|
|
36
37
|
const Logger = require('@mojaloop/central-services-logger')
|
|
37
38
|
const Time = require('@mojaloop/central-services-shared').Util.Time
|
|
38
39
|
const MLNumber = require('@mojaloop/ml-number')
|
|
39
40
|
const ErrorHandler = require('@mojaloop/central-services-error-handling')
|
|
40
41
|
const Config = require('../../lib/config')
|
|
41
42
|
|
|
43
|
+
const Metrics = require('@mojaloop/central-services-metrics')
|
|
44
|
+
|
|
42
45
|
const prepareChangeParticipantPositionTransaction = async (transferList) => {
|
|
46
|
+
const histTimerChangeParticipantPositionEnd = Metrics.getHistogram(
|
|
47
|
+
'model_position',
|
|
48
|
+
'facade_prepareChangeParticipantPositionTransaction - Metrics for position model',
|
|
49
|
+
['success', 'queryName']
|
|
50
|
+
).startTimer()
|
|
43
51
|
try {
|
|
44
52
|
const knex = await Db.getKnex()
|
|
45
53
|
const participantName = transferList[0].value.content.payload.payerFsp
|
|
46
54
|
const currencyId = transferList[0].value.content.payload.amount.currency
|
|
55
|
+
const allSettlementModels = await SettlementModelCached.getAll()
|
|
56
|
+
let settlementModels = allSettlementModels.filter(model => model.currencyId === currencyId)
|
|
57
|
+
if (settlementModels.length === 0) {
|
|
58
|
+
settlementModels = allSettlementModels.filter(model => model.currencyId === null) // Default settlement model
|
|
59
|
+
if (settlementModels.length === 0) {
|
|
60
|
+
throw ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.GENERIC_SETTLEMENT_ERROR, 'Unable to find a matching or default, Settlement Model')
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const settlementModel = settlementModels.find(sm => sm.ledgerAccountTypeId === Enum.Accounts.LedgerAccountType.POSITION)
|
|
47
64
|
const participantCurrency = await participantFacade.getByNameAndCurrency(participantName, currencyId, Enum.Accounts.LedgerAccountType.POSITION)
|
|
65
|
+
const settlementParticipantCurrency = await participantFacade.getByNameAndCurrency(participantName, currencyId, settlementModel.settlementAccountTypeId)
|
|
48
66
|
const processedTransfers = {} // The list of processed transfers - so that we can store the additional information around the decision. Most importantly the "running" position
|
|
49
67
|
const reservedTransfers = []
|
|
50
68
|
const abortedTransfers = []
|
|
@@ -52,6 +70,11 @@ const prepareChangeParticipantPositionTransaction = async (transferList) => {
|
|
|
52
70
|
const transferIdList = []
|
|
53
71
|
const limitAlarms = []
|
|
54
72
|
let sumTransfersInBatch = 0
|
|
73
|
+
const histTimerChangeParticipantPositionTransEnd = Metrics.getHistogram(
|
|
74
|
+
'model_position',
|
|
75
|
+
'facade_prepareChangeParticipantPositionTransaction_transaction - Metrics for position model',
|
|
76
|
+
['success', 'queryName']
|
|
77
|
+
).startTimer()
|
|
55
78
|
await knex.transaction(async (trx) => {
|
|
56
79
|
try {
|
|
57
80
|
const transactionTimestamp = Time.getUTCString(new Date())
|
|
@@ -73,9 +96,21 @@ const prepareChangeParticipantPositionTransaction = async (transferList) => {
|
|
|
73
96
|
|
|
74
97
|
const id = transfer.value.content.payload.transferId
|
|
75
98
|
transferIdList.push(id)
|
|
99
|
+
// DUPLICATE of TransferStateChangeModel getByTransferId
|
|
76
100
|
initialTransferStateChangePromises.push(await knex('transferStateChange').transacting(trx).where('transferId', id).orderBy('transferStateChangeId', 'desc').first())
|
|
77
101
|
}
|
|
102
|
+
const histTimerinitialTransferStateChangeListEnd = Metrics.getHistogram(
|
|
103
|
+
'model_position',
|
|
104
|
+
'facade_prepareChangeParticipantPositionTransaction_transaction_initialTransferStateChangeList - Metrics for position model',
|
|
105
|
+
['success', 'queryName']
|
|
106
|
+
).startTimer()
|
|
78
107
|
const initialTransferStateChangeList = await Promise.all(initialTransferStateChangePromises)
|
|
108
|
+
histTimerinitialTransferStateChangeListEnd({ success: true, queryName: 'facade_prepareChangeParticipantPositionTransaction_transaction_initialTransferStateChangeList' })
|
|
109
|
+
const histTimerTransferStateChangePrepareAndBatchInsertEnd = Metrics.getHistogram(
|
|
110
|
+
'model_position',
|
|
111
|
+
'facade_prepareChangeParticipantPositionTransaction_transaction_transferStateChangeBatchInsert - Metrics for position model',
|
|
112
|
+
['success', 'queryName']
|
|
113
|
+
).startTimer()
|
|
79
114
|
for (const id in initialTransferStateChangeList) {
|
|
80
115
|
const transferState = initialTransferStateChangeList[id]
|
|
81
116
|
const transfer = transferList[id].value.content.payload
|
|
@@ -95,19 +130,48 @@ const prepareChangeParticipantPositionTransaction = async (transferList) => {
|
|
|
95
130
|
}
|
|
96
131
|
const abortedTransferStateChangeList = Object.keys(abortedTransfers).length && Array.from(transferIdList.map(transferId => abortedTransfers[transferId].transferState))
|
|
97
132
|
Object.keys(abortedTransferStateChangeList).length && await knex.batchInsert('transferStateChange', abortedTransferStateChangeList).transacting(trx)
|
|
133
|
+
histTimerTransferStateChangePrepareAndBatchInsertEnd({ success: true, queryName: 'facade_prepareChangeParticipantPositionTransaction_transaction_transferStateChangeBatchInsert' })
|
|
98
134
|
// Get the effective position for this participantCurrency at the start of processing the Batch
|
|
99
135
|
// and reserved the total value of the transfers in the batch (sumTransfersInBatch)
|
|
100
|
-
const
|
|
136
|
+
const histTimerUpdateEffectivePositionEnd = Metrics.getHistogram(
|
|
137
|
+
'model_position',
|
|
138
|
+
'facade_prepareChangeParticipantPositionTransaction_transaction_UpdateEffectivePosition - Metrics for position model',
|
|
139
|
+
['success', 'queryName']
|
|
140
|
+
).startTimer()
|
|
141
|
+
const participantPositions = await knex('participantPosition')
|
|
142
|
+
.transacting(trx)
|
|
143
|
+
.whereIn('participantCurrencyId', [participantCurrency.participantCurrencyId, settlementParticipantCurrency.participantCurrencyId])
|
|
144
|
+
.forUpdate()
|
|
145
|
+
.select('*')
|
|
146
|
+
const initialParticipantPosition = participantPositions.find(position => position.participantCurrencyId === participantCurrency.participantCurrencyId)
|
|
147
|
+
const settlementParticipantPosition = participantPositions.find(position => position.participantCurrencyId === settlementParticipantCurrency.participantCurrencyId)
|
|
101
148
|
const currentPosition = new MLNumber(initialParticipantPosition.value)
|
|
102
149
|
const reservedPosition = new MLNumber(initialParticipantPosition.reservedValue)
|
|
103
150
|
const effectivePosition = currentPosition.add(reservedPosition).toFixed(Config.AMOUNT.SCALE)
|
|
104
151
|
initialParticipantPosition.reservedValue = new MLNumber(initialParticipantPosition.reservedValue).add(sumTransfersInBatch).toFixed(Config.AMOUNT.SCALE)
|
|
105
152
|
initialParticipantPosition.changedDate = transactionTimestamp
|
|
106
153
|
await knex('participantPosition').transacting(trx).where({ participantPositionId: initialParticipantPosition.participantPositionId }).update(initialParticipantPosition)
|
|
154
|
+
histTimerUpdateEffectivePositionEnd({ success: true, queryName: 'facade_prepareChangeParticipantPositionTransaction_transaction_UpdateEffectivePosition' })
|
|
107
155
|
// Get the actual position limit and calculate the available position for the transfers to use in this batch
|
|
108
156
|
// Note: see optimisation decision notes to understand the justification for the algorithm
|
|
157
|
+
const histTimerValidatePositionBatchEnd = Metrics.getHistogram(
|
|
158
|
+
'model_position',
|
|
159
|
+
'facade_prepareChangeParticipantPositionTransaction_transaction_ValidatePositionBatch - Metrics for position model',
|
|
160
|
+
['success', 'queryName']
|
|
161
|
+
).startTimer()
|
|
109
162
|
const participantLimit = await participantFacade.getParticipantLimitByParticipantCurrencyLimit(participantCurrency.participantId, participantCurrency.currencyId, Enum.Accounts.LedgerAccountType.POSITION, Enum.Accounts.ParticipantLimitType.NET_DEBIT_CAP)
|
|
110
|
-
|
|
163
|
+
// Calculate liquidity cover as per story OTC-651
|
|
164
|
+
let liquidityCover
|
|
165
|
+
let payerLimit
|
|
166
|
+
if (settlementModel.settlementDelayId === Enum.Settlements.SettlementDelay.IMMEDIATE) {
|
|
167
|
+
liquidityCover = new MLNumber(settlementParticipantPosition.value).add(new MLNumber(participantLimit.value))
|
|
168
|
+
payerLimit = new MLNumber(participantLimit.value)
|
|
169
|
+
} else {
|
|
170
|
+
liquidityCover = new MLNumber(settlementParticipantPosition.value).multiply(-1)
|
|
171
|
+
payerLimit = new MLNumber(participantLimit.value)
|
|
172
|
+
}
|
|
173
|
+
let availablePositionBasedOnLiquidityCover = liquidityCover.subtract(effectivePosition).toFixed(Config.AMOUNT.SCALE)
|
|
174
|
+
let availablePositionBasedOnPayerLimit = payerLimit.subtract(effectivePosition).toFixed(Config.AMOUNT.SCALE)
|
|
111
175
|
/* Validate entire batch if availablePosition >= sumTransfersInBatch - the impact is that applying per transfer rules would require to be handled differently
|
|
112
176
|
since further rules are expected we do not do this at this point
|
|
113
177
|
As we enter this next step the order in which the transfer is processed against the Position is critical.
|
|
@@ -117,19 +181,32 @@ const prepareChangeParticipantPositionTransaction = async (transferList) => {
|
|
|
117
181
|
let sumReserved = 0 // Record the sum of the transfers we allow to progress to RESERVED
|
|
118
182
|
for (const transferId in reservedTransfers) {
|
|
119
183
|
const { transfer, transferState, rawMessage, transferAmount } = reservedTransfers[transferId]
|
|
120
|
-
if (new MLNumber(
|
|
121
|
-
availablePosition = new MLNumber(availablePosition).subtract(transferAmount).toFixed(Config.AMOUNT.SCALE)
|
|
122
|
-
transferState.transferStateId = Enum.Transfers.TransferState.RESERVED
|
|
123
|
-
sumReserved = new MLNumber(sumReserved).add(transferAmount).toFixed(Config.AMOUNT.SCALE) /* actually used */
|
|
124
|
-
} else {
|
|
184
|
+
if (new MLNumber(availablePositionBasedOnLiquidityCover).toNumber() < transferAmount.toNumber()) {
|
|
125
185
|
transferState.transferStateId = Enum.Transfers.TransferInternalState.ABORTED_REJECTED
|
|
126
186
|
transferState.reason = ErrorHandler.Enums.FSPIOPErrorCodes.PAYER_FSP_INSUFFICIENT_LIQUIDITY.message
|
|
127
|
-
|
|
187
|
+
reservedTransfers[transferId].fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PAYER_FSP_INSUFFICIENT_LIQUIDITY, null, null, null, rawMessage.value.content.payload.extensionList)
|
|
188
|
+
rawMessage.value.content.payload = reservedTransfers[transferId].fspiopError.toApiErrorObject(Config.ERROR_HANDLING)
|
|
189
|
+
} else if (new MLNumber(availablePositionBasedOnPayerLimit).toNumber() < transferAmount.toNumber()) {
|
|
190
|
+
transferState.transferStateId = Enum.Transfers.TransferInternalState.ABORTED_REJECTED
|
|
191
|
+
transferState.reason = ErrorHandler.Enums.FSPIOPErrorCodes.PAYER_LIMIT_ERROR.message
|
|
192
|
+
reservedTransfers[transferId].fspiopError = ErrorHandler.Factory.createFSPIOPError(ErrorHandler.Enums.FSPIOPErrorCodes.PAYER_LIMIT_ERROR, null, null, null, rawMessage.value.content.payload.extensionList)
|
|
193
|
+
rawMessage.value.content.payload = reservedTransfers[transferId].fspiopError.toApiErrorObject(Config.ERROR_HANDLING)
|
|
194
|
+
} else {
|
|
195
|
+
availablePositionBasedOnLiquidityCover = new MLNumber(availablePositionBasedOnLiquidityCover).subtract(transferAmount).toFixed(Config.AMOUNT.SCALE)
|
|
196
|
+
availablePositionBasedOnPayerLimit = new MLNumber(availablePositionBasedOnPayerLimit).subtract(transferAmount).toFixed(Config.AMOUNT.SCALE)
|
|
197
|
+
transferState.transferStateId = Enum.Transfers.TransferState.RESERVED
|
|
198
|
+
sumReserved = new MLNumber(sumReserved).add(transferAmount).toFixed(Config.AMOUNT.SCALE) /* actually used */
|
|
128
199
|
}
|
|
129
200
|
const runningPosition = new MLNumber(currentPosition).add(sumReserved).toFixed(Config.AMOUNT.SCALE) /* effective position */
|
|
130
201
|
const runningReservedValue = new MLNumber(sumTransfersInBatch).subtract(sumReserved).toFixed(Config.AMOUNT.SCALE)
|
|
131
202
|
processedTransfers[transferId] = { transferState, transfer, rawMessage, transferAmount, runningPosition, runningReservedValue }
|
|
132
203
|
}
|
|
204
|
+
histTimerValidatePositionBatchEnd({ success: true, queryName: 'facade_prepareChangeParticipantPositionTransaction_transaction_ValidatePositionBatch' })
|
|
205
|
+
const histTimerUpdateParticipantPositionEnd = Metrics.getHistogram(
|
|
206
|
+
'model_position',
|
|
207
|
+
'facade_prepareChangeParticipantPositionTransaction_transaction_UpdateParticipantPosition - Metrics for position model',
|
|
208
|
+
['success', 'queryName']
|
|
209
|
+
).startTimer()
|
|
133
210
|
/*
|
|
134
211
|
Update the participantPosition with the eventual impact of the Batch
|
|
135
212
|
So the position moves forward by the sum of the transfers actually reserved (sumReserved)
|
|
@@ -142,13 +219,19 @@ const prepareChangeParticipantPositionTransaction = async (transferList) => {
|
|
|
142
219
|
changedDate: transactionTimestamp
|
|
143
220
|
})
|
|
144
221
|
// TODO this limit needs to be clarified
|
|
145
|
-
if (processedPositionValue.toNumber() >
|
|
222
|
+
if (processedPositionValue.toNumber() > liquidityCover.multiply(participantLimit.thresholdAlarmPercentage).toNumber()) {
|
|
146
223
|
limitAlarms.push(participantLimit)
|
|
147
224
|
}
|
|
225
|
+
histTimerUpdateParticipantPositionEnd({ success: true, queryName: 'facade_prepareChangeParticipantPositionTransaction_transaction_UpdateParticipantPosition' })
|
|
148
226
|
/*
|
|
149
227
|
Persist the transferStateChanges and associated participantPositionChange entry to record the running position
|
|
150
228
|
The transferStateChanges need to be persisted first (by INSERTing) to have the PK reference
|
|
151
229
|
*/
|
|
230
|
+
const histTimerPersistTransferStateChangeEnd = Metrics.getHistogram(
|
|
231
|
+
'model_position',
|
|
232
|
+
'facade_prepareChangeParticipantPositionTransaction_transaction_PersistTransferState - Metrics for position model',
|
|
233
|
+
['success', 'queryName']
|
|
234
|
+
).startTimer()
|
|
152
235
|
await knex('transfer').transacting(trx).forUpdate().whereIn('transferId', transferIdList).select('*')
|
|
153
236
|
const processedTransferStateChangeList = Object.keys(processedTransfers).length && Array.from(transferIdList.map(transferId => processedTransfers[transferId].transferState))
|
|
154
237
|
const processedTransferStateChangeIdList = processedTransferStateChangeList && Object.keys(processedTransferStateChangeList).length && await knex.batchInsert('transferStateChange', processedTransferStateChangeList).transacting(trx)
|
|
@@ -166,10 +249,13 @@ const prepareChangeParticipantPositionTransaction = async (transferList) => {
|
|
|
166
249
|
batchParticipantPositionChange.push(participantPositionChange)
|
|
167
250
|
}
|
|
168
251
|
batchParticipantPositionChange.length && await knex.batchInsert('participantPositionChange', batchParticipantPositionChange).transacting(trx)
|
|
169
|
-
|
|
252
|
+
histTimerPersistTransferStateChangeEnd({ success: true, queryName: 'facade_prepareChangeParticipantPositionTransaction_transaction_PersistTransferState' })
|
|
253
|
+
await trx.commit()
|
|
254
|
+
histTimerChangeParticipantPositionTransEnd({ success: true, queryName: 'facade_prepareChangeParticipantPositionTransaction_transaction' })
|
|
170
255
|
} catch (err) {
|
|
171
|
-
Logger.error(err)
|
|
172
|
-
await trx.rollback
|
|
256
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
257
|
+
await trx.rollback()
|
|
258
|
+
histTimerChangeParticipantPositionTransEnd({ success: false, queryName: 'facade_prepareChangeParticipantPositionTransaction_transaction' })
|
|
173
259
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
174
260
|
}
|
|
175
261
|
})
|
|
@@ -178,14 +264,21 @@ const prepareChangeParticipantPositionTransaction = async (transferList) => {
|
|
|
178
264
|
? reservedTransfers[transferId]
|
|
179
265
|
: abortedTransfers[transferId]
|
|
180
266
|
))
|
|
267
|
+
histTimerChangeParticipantPositionEnd({ success: true, queryName: 'facade_prepareChangeParticipantPositionTransaction' })
|
|
181
268
|
return { preparedMessagesList, limitAlarms }
|
|
182
269
|
} catch (err) {
|
|
183
|
-
Logger.error(err)
|
|
270
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
271
|
+
histTimerChangeParticipantPositionEnd({ success: false, queryName: 'facade_prepareChangeParticipantPositionTransaction' })
|
|
184
272
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
185
273
|
}
|
|
186
274
|
}
|
|
187
275
|
|
|
188
276
|
const changeParticipantPositionTransaction = async (participantCurrencyId, isReversal, amount, transferStateChange) => {
|
|
277
|
+
const histTimerChangeParticipantPositionTransactionEnd = Metrics.getHistogram(
|
|
278
|
+
'model_position',
|
|
279
|
+
'facade_changeParticipantPositionTransaction - Metrics for position model',
|
|
280
|
+
['success', 'queryName']
|
|
281
|
+
).startTimer()
|
|
189
282
|
try {
|
|
190
283
|
const knex = await Db.getKnex()
|
|
191
284
|
await knex.transaction(async (trx) => {
|
|
@@ -214,16 +307,17 @@ const changeParticipantPositionTransaction = async (participantCurrencyId, isRev
|
|
|
214
307
|
createdDate: transactionTimestamp
|
|
215
308
|
}
|
|
216
309
|
await knex('participantPositionChange').transacting(trx).insert(participantPositionChange)
|
|
217
|
-
await trx.commit
|
|
310
|
+
await trx.commit()
|
|
311
|
+
histTimerChangeParticipantPositionTransactionEnd({ success: true, queryName: 'facade_changeParticipantPositionTransaction' })
|
|
218
312
|
} catch (err) {
|
|
219
|
-
await trx.rollback
|
|
313
|
+
await trx.rollback()
|
|
220
314
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
221
315
|
}
|
|
222
316
|
}).catch((err) => {
|
|
223
317
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
224
318
|
})
|
|
225
319
|
} catch (err) {
|
|
226
|
-
Logger.error(err)
|
|
320
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
227
321
|
throw ErrorHandler.Factory.reformatFSPIOPError(err)
|
|
228
322
|
}
|
|
229
323
|
}
|
|
@@ -244,7 +338,7 @@ const changeParticipantPositionTransaction = async (participantCurrencyId, isRev
|
|
|
244
338
|
|
|
245
339
|
const getByNameAndCurrency = async (name, ledgerAccountTypeId, currencyId = null) => {
|
|
246
340
|
try {
|
|
247
|
-
return Db.participantPosition.query(builder => {
|
|
341
|
+
return Db.from('participantPosition').query(builder => {
|
|
248
342
|
return builder.innerJoin('participantCurrency AS pc', 'participantPosition.participantCurrencyId', 'pc.participantCurrencyId')
|
|
249
343
|
.innerJoin('participant AS p', 'pc.participantId', 'p.participantId')
|
|
250
344
|
.where({
|
|
@@ -268,7 +362,7 @@ const getByNameAndCurrency = async (name, ledgerAccountTypeId, currencyId = null
|
|
|
268
362
|
|
|
269
363
|
const getAllByNameAndCurrency = async (name, currencyId = null) => {
|
|
270
364
|
try {
|
|
271
|
-
return Db.participantPosition.query(builder => {
|
|
365
|
+
return Db.from('participantPosition').query(builder => {
|
|
272
366
|
return builder.innerJoin('participantCurrency AS pc', 'participantPosition.participantCurrencyId', 'pc.participantCurrencyId')
|
|
273
367
|
.innerJoin('ledgerAccountType AS lap', 'lap.ledgerAccountTypeId', 'pc.ledgerAccountTypeId')
|
|
274
368
|
.innerJoin('participant AS p', 'pc.participantId', 'p.participantId')
|
|
@@ -29,27 +29,27 @@ const Logger = require('@mojaloop/central-services-logger')
|
|
|
29
29
|
|
|
30
30
|
const insert = async (participantPosition) => {
|
|
31
31
|
try {
|
|
32
|
-
return await Db.participantPosition.insert(participantPosition)
|
|
32
|
+
return await Db.from('participantPosition').insert(participantPosition)
|
|
33
33
|
} catch (err) {
|
|
34
|
-
Logger.error(err)
|
|
34
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
35
35
|
throw err
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
const update = async (participantPosition) => {
|
|
40
40
|
try {
|
|
41
|
-
return await Db.participantPosition.update({ participantCurrencyId: participantPosition.participantCurrencyId }, { value: participantPosition.value, reservedValue: participantPosition.reservedValue, changedDate: new Date() })
|
|
41
|
+
return await Db.from('participantPosition').update({ participantCurrencyId: participantPosition.participantCurrencyId }, { value: participantPosition.value, reservedValue: participantPosition.reservedValue, changedDate: new Date() })
|
|
42
42
|
} catch (err) {
|
|
43
|
-
Logger.error(err)
|
|
43
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
44
44
|
throw err
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
const getPositionByCurrencyId = async (participantCurrencyId) => {
|
|
49
49
|
try {
|
|
50
|
-
return await Db.participantPosition.findOne({ participantCurrencyId })
|
|
50
|
+
return await Db.from('participantPosition').findOne({ participantCurrencyId })
|
|
51
51
|
} catch (err) {
|
|
52
|
-
Logger.error(err)
|
|
52
|
+
Logger.isErrorEnabled && Logger.error(err)
|
|
53
53
|
throw err
|
|
54
54
|
}
|
|
55
55
|
}
|