Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ime-5): extension list caching changes #530

Open
wants to merge 1 commit into
base: minor/iso
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/api-svc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
},
"dependencies": {
"@koa/cors": "^5.0.0",
"@mojaloop/api-snippets": "17.7.8",
"@mojaloop/api-snippets": "17.7.8",
"@mojaloop/central-services-error-handling": "^13.0.3",
"@mojaloop/central-services-logger": "^11.5.2",
"@mojaloop/central-services-metrics": "^12.4.3",
Expand Down
24 changes: 12 additions & 12 deletions modules/api-svc/src/InboundServer/handlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ const postQuotes = async (ctx) => {
ctx.state.logger.isDebugEnabled && ctx.state.logger.push(ctx.request.body).debug('Transforming incoming ISO20022 post quotes body to FSPIOP');
// store the original request body in the context for later use
quoteRequest.isoPostQuote = ctx.request.body;
const target = await TransformFacades.FSPIOPISO20022.quotes.post({ body: ctx.request.body });
const target = await TransformFacades.FSPIOPISO20022.quotes.post({ body: ctx.request.body }, { rollUpUnmappedAsExtensions: true });
ctx.request.body = target.body;
}

Expand Down Expand Up @@ -225,7 +225,7 @@ const postTransfers = async (ctx) => {
if (ctx.state.conf.isIsoApi) {
// we need to transform the incoming request body from iso20022 to fspiop
ctx.state.logger.isDebugEnabled && ctx.state.logger.push(ctx.request.body).debug('Transforming incoming ISO20022 post transfers body to FSPIOP');
const target = await TransformFacades.FSPIOPISO20022.transfers.post({ body: ctx.request.body });
const target = await TransformFacades.FSPIOPISO20022.transfers.post({ body: ctx.request.body }, { rollUpUnmappedAsExtensions: true });
ctx.request.body = target.body;
}

Expand Down Expand Up @@ -441,7 +441,7 @@ const putPartiesByTypeAndId = async (ctx) => {
if (ctx.state.conf.isIsoApi) {
// we need to transform the incoming request body from iso20022 to fspiop
ctx.state.logger.isDebugEnabled && ctx.state.logger.push(ctx.request.body).debug('Transforming incoming ISO20022 put parties body to FSPIOP');
const target = await TransformFacades.FSPIOPISO20022.parties.put({ body: ctx.request.body });
const target = await TransformFacades.FSPIOPISO20022.parties.put({ body: ctx.request.body }, { rollUpUnmappedAsExtensions: true });
ctx.request.body = target.body;
}

Expand Down Expand Up @@ -475,7 +475,7 @@ const putQuoteById = async (ctx) => {
ctx.request.originalIso20022QuoteResponse = ctx.request.body;
// we need to transform the incoming request body from iso20022 to fspiop
ctx.state.logger.isDebugEnabled && ctx.state.logger.push(ctx.request.body).debug('Transforming incoming ISO20022 put quotes body to FSPIOP');
const target = await TransformFacades.FSPIOPISO20022.quotes.put({ body: ctx.request.body });
const target = await TransformFacades.FSPIOPISO20022.quotes.put({ body: ctx.request.body }, { rollUpUnmappedAsExtensions: true });
ctx.request.body = target.body;
}

Expand Down Expand Up @@ -514,7 +514,7 @@ const putQuotesByIdError = async (ctx) => {
if (ctx.state.conf.isIsoApi) {
// we need to transform the incoming request body from iso20022 to fspiop
ctx.state.logger.isDebugEnabled && ctx.state.logger.push(ctx.request.body).debug('Transforming incoming ISO20022 putError quotes body to FSPIOP');
const target = await TransformFacades.FSPIOPISO20022.quotes.putError({ body: ctx.request.body });
const target = await TransformFacades.FSPIOPISO20022.quotes.putError({ body: ctx.request.body }, { rollUpUnmappedAsExtensions: true });
ctx.request.body = target.body;
}

Expand Down Expand Up @@ -646,7 +646,7 @@ const putTransfersById = async (ctx) => {
if (ctx.state.conf.isIsoApi) {
// we need to transform the incoming request body from iso20022 to fspiop
ctx.state.logger.isDebugEnabled && ctx.state.logger.push(ctx.request.body).debug('Transforming incoming ISO20022 put transfers body to FSPIOP');
const target = await TransformFacades.FSPIOPISO20022.transfers.put({ body: ctx.request.body });
const target = await TransformFacades.FSPIOPISO20022.transfers.put({ body: ctx.request.body }, { rollUpUnmappedAsExtensions: true });
ctx.request.body = target.body;
}

Expand Down Expand Up @@ -703,7 +703,7 @@ const putPartiesByTypeAndIdError = async(ctx) => {
if (ctx.state.conf.isIsoApi) {
// we need to transform the incoming request body from iso20022 to fspiop
ctx.state.logger.isDebugEnabled && ctx.state.logger.push(ctx.request.body).debug('Transforming incoming ISO20022 putError parties body to FSPIOP');
const target = await TransformFacades.FSPIOPISO20022.parties.putError({ body: ctx.request.body });
const target = await TransformFacades.FSPIOPISO20022.parties.putError({ body: ctx.request.body }, { rollUpUnmappedAsExtensions: true });
ctx.request.body = target.body;
}

Expand Down Expand Up @@ -739,7 +739,7 @@ const putTransfersByIdError = async (ctx) => {
if (ctx.state.conf.isIsoApi) {
// we need to transform the incoming request body from iso20022 to fspiop
ctx.state.logger.isDebugEnabled && ctx.state.logger.push(ctx.request.body).debug('Transforming incoming ISO20022 putError transfers body to FSPIOP');
const target = await TransformFacades.FSPIOPISO20022.transfers.putError({ body: ctx.request.body });
const target = await TransformFacades.FSPIOPISO20022.transfers.putError({ body: ctx.request.body }, { rollUpUnmappedAsExtensions: true });
ctx.request.body = target.body;
}

Expand Down Expand Up @@ -967,7 +967,7 @@ const healthCheck = async(ctx) => {
const postFxQuotes = async (ctx) => {
if (ctx.state.conf.isIsoApi) {
ctx.state.logger.isDebugEnabled && ctx.state.logger.push(ctx.request.body).debug('Transforming incoming ISO20022 post fxQuotes body to FSPIOP');
const target = await TransformFacades.FSPIOPISO20022.fxQuotes.post({ body: ctx.request.body });
const target = await TransformFacades.FSPIOPISO20022.fxQuotes.post({ body: ctx.request.body }, { rollUpUnmappedAsExtensions: true });
ctx.request.body = target.body;
}

Expand All @@ -993,7 +993,7 @@ const createPutFxQuotesHandler = (success) => async (ctx) => {
if (ctx.state.conf.isIsoApi) {
const method = success ? 'put' : 'putError';
ctx.state.logger.isDebugEnabled && ctx.state.logger.push(ctx.request.body).debug(`Transforming incoming ISO20022 ${method} fxQuotes body to FSPIOP`);
const target = await TransformFacades.FSPIOPISO20022.fxQuotes[method]({ body: ctx.request.body });
const target = await TransformFacades.FSPIOPISO20022.fxQuotes[method]({ body: ctx.request.body }, { rollUpUnmappedAsExtensions: true });
ctx.request.body = target.body;
}

Expand Down Expand Up @@ -1024,7 +1024,7 @@ const createPutFxQuotesHandler = (success) => async (ctx) => {
const postFxTransfers = async (ctx) => {
if (ctx.state.conf.isIsoApi) {
ctx.state.logger.isDebugEnabled && ctx.state.logger.push(ctx.request.body).debug('Transforming incoming ISO20022 post fxTransfers body to FSPIOP');
const target = await TransformFacades.FSPIOPISO20022.fxTransfers.post({ body: ctx.request.body });
const target = await TransformFacades.FSPIOPISO20022.fxTransfers.post({ body: ctx.request.body }, { rollUpUnmappedAsExtensions: true });
ctx.request.body = target.body;
}

Expand Down Expand Up @@ -1065,7 +1065,7 @@ const createPutFxTransfersHandler = (success) => async (ctx) => {
if (ctx.state.conf.isIsoApi) {
const method = success ? 'put' : 'putError';
ctx.state.logger.isDebugEnabled && ctx.state.logger.push(ctx.request.body).debug(`Transforming incoming ISO20022 ${method} fxTransfers body to FSPIOP`);
const target = await TransformFacades.FSPIOPISO20022.fxTransfers[method]({ body: ctx.request.body });
const target = await TransformFacades.FSPIOPISO20022.fxTransfers[method]({ body: ctx.request.body }, { rollUpUnmappedAsExtensions: true });
ctx.request.body = target.body;
}

Expand Down
4 changes: 4 additions & 0 deletions modules/api-svc/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,4 +241,8 @@ module.exports = {
// - 1
// - 4
ilpVersion: env.get('ILP_VERSION').default('1').asString(),

// Redis key ttl when stored in the cache, if value is used as zero it will
// persist throughout the session , value used is in seconds
redisCacheTtl: env.get('REDIS_CACHE_TTL').default('0').asInt()
};
10 changes: 8 additions & 2 deletions modules/api-svc/src/lib/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,13 +342,19 @@ class Cache {
*
* @param key {string} - cache key
* @param value {string} - cache value
* @param ttl {number} - cache ttl in seconds
*/
async set(key, value) {
async set(key, value, ttl=0 ) {
//if we are given an object, turn it into a string
if(typeof(value) !== 'string') {
value = JSON.stringify(value);
}
await this._client.set(key, value);
// If ttl is positive i.e >0 then set expiry time as ttl in seconds
if(ttl > 0)
await this._client.set(key, value, { 'EX': ttl });
else
await this._client.set(key, value);

}

/**
Expand Down
5 changes: 3 additions & 2 deletions modules/api-svc/src/lib/model/InboundTransfersModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class InboundTransfersModel {
secret: config.ilpSecret,
logger: config.logger,
});
this._cacheTtl = config.redisCacheTtl;
}

updateStateWithError(err) {
Expand Down Expand Up @@ -1061,7 +1062,7 @@ class InboundTransfersModel {
*/
async _save() {
try {
const res = await this._cache.set(`transferModel_in_${this.data.transferId}`, this.data);
const res = await this._cache.set(`transferModel_in_${this.data.transferId}`, this.data, this._cacheTtl);
this._logger.push({ res }).debug('Persisted transfer model in cache');
}
catch(err) {
Expand Down Expand Up @@ -1089,7 +1090,7 @@ class InboundTransfersModel {
// todo: combine with this._save
async saveFxState() { // fxQuote + fxTransfer
const key = this.makeFxQuoteCacheKey(this.data?.conversionId);
const res = await this._cache.set(key, this.data);
const res = await this._cache.set(key, this.data, this._cacheTtl);
this._logger.push({ key, res }).log('fxState is saved in cache');
}

Expand Down
36 changes: 35 additions & 1 deletion modules/api-svc/src/lib/model/OutboundTransfersModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class OutboundTransfersModel {
if (this._autoAcceptParty && this._multiplePartiesResponse) {
throw new Error('Conflicting config options provided: autoAcceptParty and multiplePartiesResponse');
}

this._cacheTtl = config.redisCacheTtl;

this._requests = new MojaloopRequests({
logger: this._logger,
Expand Down Expand Up @@ -1152,14 +1154,46 @@ class OutboundTransfersModel {
async _save() {
try {
this.data.currentState = this.stateMachine.state;
const res = await this._cache.set(`transferModel_out_${this.data.transferId}`, this.data);
const res = await this._cache.set(`transferModel_out_${this.data.transferId}`, this.data, this._cacheTtl);
// function to modify this.data before saving to cache for UI.
const modifiedData = this._modifyDataForUi(this.data);
// save to a UI key, using a modifiedData, as we don't want any side effects to happen on original data
// No ttl set as it will persist throughout the session
await this._cache.set(`transferUI_out_${this.data.transferId}`, modifiedData);
this._logger.isDebugEnabled && this._logger.push({ res }).debug('Persisted transfer model in cache');
}
catch (err) {
this._logger.isErrorEnabled && this._logger.push({ err, data: this.data }).error('Error saving transfer model');
throw err;
}
}

/**
* Modifies the data being stored in the cache for UI before it is store.
* Works on a copy of original object to avoid side effects
*/
_modifyDataForUi( data ){
// deep cloning to avoid side effects
let modifiedData = JSON.parse(JSON.stringify(data));
// Removing iso quote response and extension lists
if(modifiedData.getPartiesResponse && modifiedData.getPartiesResponse.body && modifiedData.getPartiesResponse.body.extensionList)
modifiedData.getPartiesResponse.body.extensionList = undefined;
if(modifiedData.fxQuoteResponse && modifiedData.fxQuoteResponse.body && modifiedData.fxQuoteResponse.body.extensionList)
modifiedData.fxQuoteResponse.body.extensionList = undefined;
if(modifiedData.quoteResponse && modifiedData.quoteResponse.originalIso20022QuoteResponse){
modifiedData.quoteResponse.originalIso20022QuoteResponse = undefined;
}
if(modifiedData.quoteResponse && modifiedData.quoteResponse.body && modifiedData.quoteResponse.body.extensionList){
modifiedData.quoteResponse.body.extensionList = undefined;
}
if(modifiedData.fxTransferResponse && modifiedData.fxTransferResponse.body && modifiedData.fxTransferResponse.body.extensionList){
modifiedData.fxTransferResponse.body.extensionList = undefined;
}
if(modifiedData.fulfil && modifiedData.fulfil.body && modifiedData.fulfil.body.extensionList){
modifiedData.fulfil.body.extensionList = undefined;
}
return modifiedData;
}


/**
Expand Down