diff --git a/config/default.json b/config/default.json index 99d3c1de..5a74e47e 100644 --- a/config/default.json +++ b/config/default.json @@ -79,5 +79,6 @@ } }, "API_DOC_ENDPOINTS_ENABLED": true, - "FEATURE_ENABLE_EXTENDED_PARTY_ID_TYPE": false + "FEATURE_ENABLE_EXTENDED_PARTY_ID_TYPE": false, + "ASYNC_CONCURRENCY": 5 } diff --git a/package-lock.json b/package-lock.json index 3fee2e05..61f505c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "account-lookup-service", - "version": "15.2.0", + "version": "15.3.0-snapshot.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "account-lookup-service", - "version": "15.2.0", + "version": "15.3.0-snapshot.2", "license": "Apache-2.0", "dependencies": { "@hapi/basic": "7.0.2", @@ -28,6 +28,7 @@ "@now-ims/hapi-now-auth": "2.1.0", "ajv": "8.12.0", "ajv-keywords": "5.1.0", + "async": "^3.2.5", "blipp": "4.0.2", "commander": "11.1.0", "hapi-auth-bearer-token": "8.0.0", @@ -41,7 +42,7 @@ "uuid4": "2.0.3" }, "devDependencies": { - "@types/jest": "29.5.10", + "@types/jest": "29.5.11", "audit-ci": "^6.6.1", "axios": "1.6.2", "docdash": "2.0.2", @@ -49,7 +50,7 @@ "jest": "29.7.0", "jest-junit": "16.0.0", "jsdoc": "4.0.2", - "nodemon": "3.0.1", + "nodemon": "3.0.2", "npm-audit-resolver": "3.0.0-RC.0", "npm-check-updates": "16.14.11", "nyc": "15.1.0", @@ -2901,9 +2902,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.10", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.10.tgz", - "integrity": "sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==", + "version": "29.5.11", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.11.tgz", + "integrity": "sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -3386,9 +3387,9 @@ } }, "node_modules/async": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", - "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" }, "node_modules/asynciterator.prototype": { "version": "1.0.0", @@ -11291,13 +11292,13 @@ "dev": true }, "node_modules/nodemon": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.1.tgz", - "integrity": "sha512-g9AZ7HmkhQkqXkRc20w+ZfQ73cHLbE8hnPbtaFbFtCumZsjyMhKk9LajQ07U5Ux28lvFjZ5X7HvWR1xzU8jHVw==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.2.tgz", + "integrity": "sha512-9qIN2LNTrEzpOPBaWHTm4Asy1LxXLSickZStAQ4IZe7zsoIpD/A7LWxhZV3t4Zu352uBcqVnRsDXSMR2Sc3lTA==", "dev": true, "dependencies": { "chokidar": "^3.5.2", - "debug": "^3.2.7", + "debug": "^4", "ignore-by-default": "^1.0.1", "minimatch": "^3.1.2", "pstree.remy": "^1.1.8", @@ -11318,15 +11319,6 @@ "url": "https://opencollective.com/nodemon" } }, - "node_modules/nodemon/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, "node_modules/nodemon/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", diff --git a/package.json b/package.json index 56a721e6..f96cbb66 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "account-lookup-service", "description": "Account Lookup Service is used to validate Party and Participant lookups.", - "version": "15.2.0", + "version": "15.3.0-snapshot.2", "license": "Apache-2.0", "author": "ModusBox", "contributors": [ @@ -94,6 +94,7 @@ "@now-ims/hapi-now-auth": "2.1.0", "ajv": "8.12.0", "ajv-keywords": "5.1.0", + "async": "^3.2.5", "blipp": "4.0.2", "commander": "11.1.0", "hapi-auth-bearer-token": "8.0.0", @@ -107,7 +108,7 @@ "uuid4": "2.0.3" }, "devDependencies": { - "@types/jest": "29.5.10", + "@types/jest": "29.5.11", "audit-ci": "^6.6.1", "axios": "1.6.2", "docdash": "2.0.2", @@ -115,7 +116,7 @@ "jest": "29.7.0", "jest-junit": "16.0.0", "jsdoc": "4.0.2", - "nodemon": "3.0.1", + "nodemon": "3.0.2", "npm-audit-resolver": "3.0.0-RC.0", "npm-check-updates": "16.14.11", "nyc": "15.1.0", diff --git a/src/handlers/parties/{Type}/{ID}.js b/src/handlers/parties/{Type}/{ID}.js index 81576f2b..6d13f811 100644 --- a/src/handlers/parties/{Type}/{ID}.js +++ b/src/handlers/parties/{Type}/{ID}.js @@ -29,6 +29,24 @@ const EventSdk = require('@mojaloop/event-sdk') const LibUtil = require('../../../lib/util') const parties = require('../../../domain/parties') const Metrics = require('@mojaloop/central-services-metrics') +const Async = require('async') +const Config = require('../../../lib/config') + +const asyncQueue1 = Async.queue(function (task, callback) { + parties.getPartiesByTypeAndID(task.headers, task.params, task.method, task.query, task.span).then(() => { + callback(null) + }).catch((err) => { + callback(err) + }) +}, Config.ASYNC_CONCURRENCY) + +const asyncQueue2 = Async.queue(function (task, callback) { + parties.putPartiesByTypeAndID(task.headers, task.params, task.method, task.payload, task.dataUri).then(() => { + callback(null) + }).catch((err) => { + callback(err) + }) +}, Config.ASYNC_CONCURRENCY) /** * Operations on /parties/{Type}/{ID} @@ -56,9 +74,20 @@ module.exports = { }, EventSdk.AuditEventAction.start) // Here we call an async function- but as we send an immediate sync response, _all_ errors // _must_ be handled by getPartiesByTypeAndID. - parties.getPartiesByTypeAndID(request.headers, request.params, request.method, request.query, span, request.server.app.cache).catch(err => { - request.server.log(['error'], `ERROR - getPartiesByTypeAndID: ${LibUtil.getStackOrInspect(err)}`) + asyncQueue1.push({ + headers: { ...request.headers }, + params: { ...request.params }, + method: request.method, + query: { ...request.query }, + span + }, function (err) { + if (err) { + request.server.log(['error'], `ERROR - getPartiesByTypeAndID: ${LibUtil.getStackOrInspect(err)}`) + } }) + // parties.getPartiesByTypeAndID(request.headers, request.params, request.method, request.query, span).catch(err => { + // request.server.log(['error'], `ERROR - getPartiesByTypeAndID: ${LibUtil.getStackOrInspect(err)}`) + // }) histTimerEnd({ success: true }) return h.response().code(202) }, @@ -85,9 +114,20 @@ module.exports = { }, EventSdk.AuditEventAction.start) // Here we call an async function- but as we send an immediate sync response, _all_ errors // _must_ be handled by putPartiesByTypeAndID. - parties.putPartiesByTypeAndID(request.headers, request.params, request.method, request.payload, request.dataUri).catch(err => { - request.server.log(['error'], `ERROR - putPartiesByTypeAndID: ${LibUtil.getStackOrInspect(err)}`) + asyncQueue2.push({ + headers: { ...request.headers }, + params: { ...request.params }, + method: request.method, + payload: { ...request.payload }, + dataUri: request.dataUri + }, function (err) { + if (err) { + request.server.log(['error'], `ERROR - putPartiesByTypeAndID: ${LibUtil.getStackOrInspect(err)}`) + } }) + // parties.putPartiesByTypeAndID(request.headers, request.params, request.method, request.payload, request.dataUri).catch(err => { + // request.server.log(['error'], `ERROR - putPartiesByTypeAndID: ${LibUtil.getStackOrInspect(err)}`) + // }) histTimerEnd({ success: true }) return h.response().code(200) } diff --git a/src/lib/config.js b/src/lib/config.js index 18e231ca..6d008d6e 100644 --- a/src/lib/config.js +++ b/src/lib/config.js @@ -155,7 +155,8 @@ const config = { JWS_SIGNING_KEY_PATH: RC.ENDPOINT_SECURITY.JWS.JWS_SIGNING_KEY_PATH, API_DOC_ENDPOINTS_ENABLED: RC.API_DOC_ENDPOINTS_ENABLED || false, FEATURE_ENABLE_EXTENDED_PARTY_ID_TYPE: RC.FEATURE_ENABLE_EXTENDED_PARTY_ID_TYPE || false, - PROTOCOL_VERSIONS: getProtocolVersions(DEFAULT_PROTOCOL_VERSION, RC.PROTOCOL_VERSIONS) + PROTOCOL_VERSIONS: getProtocolVersions(DEFAULT_PROTOCOL_VERSION, RC.PROTOCOL_VERSIONS), + ASYNC_CONCURRENCY: RC.ASYNC_CONCURRENCY || 5 } if (config.JWS_SIGN) { diff --git a/src/models/oracle/oracleEndpointCached.js b/src/models/oracle/oracleEndpointCached.js index cd88220a..5b3b665c 100644 --- a/src/models/oracle/oracleEndpointCached.js +++ b/src/models/oracle/oracleEndpointCached.js @@ -76,7 +76,8 @@ const getOracleEndpointCached = async (params) => { exports.initialize = async () => { /* Register as cache client */ const oracleEndpointCacheClientMeta = { - id: 'oracleEndpoints' + id: 'oracleEndpoints', + preloadCache: async () => Promise.resolve() } cacheClient = Cache.registerCacheClient(oracleEndpointCacheClientMeta) diff --git a/src/server.js b/src/server.js index 858afcd3..9ec5d6e3 100644 --- a/src/server.js +++ b/src/server.js @@ -41,6 +41,7 @@ const Migrator = require('./lib/migrator') const Handlers = require('./handlers') const Routes = require('./handlers/routes') const Cache = require('./lib/cache') +const OracleEndpointCache = require('./models/oracle/oracleEndpointCached') const connectDatabase = async () => { return Db.connect(Config.DATABASE) @@ -77,7 +78,8 @@ const createServer = async (port, api, routes, isAdmin) => { } }) server.app.cache = Cache.registerCacheClient({ - id: 'serverGeneralCache' + id: 'serverGeneralCache', + preloadCache: async () => Promise.resolve() }) await Plugins.registerPlugins(server, api, isAdmin) await server.ext([ @@ -119,6 +121,8 @@ const initializeApi = async (port = Config.API_PORT) => { Logger.isInfoEnabled && Logger.info(`Server running on ${server.info.host}:${server.info.port}`) await ParticipantEndpointCache.initializeCache(Config.CENTRAL_SHARED_ENDPOINT_CACHE_CONFIG) await ParticipantCache.initializeCache(Config.CENTRAL_SHARED_PARTICIPANT_CACHE_CONFIG) + await OracleEndpointCache.initialize() + await Cache.initCache() return server }