@mojaloop/inter-scheme-proxy-cache-lib
Version:
Common component, that provides scheme proxy caching mapping (ISPC)
1 lines • 35.2 kB
Source Map (JSON)
{"version":3,"sources":["../src/validation.ts","../src/lib/storages/RedisProxyCache.ts","../src/lib/createProxyCache.ts"],"sourcesContent":["/*****\n License\n --------------\n Copyright © 2020-2025 Mojaloop Foundation\n The Mojaloop files are made available by the Mojaloop 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\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n 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.\n\n Contributors\n --------------\n This is the official list of the Mojaloop project contributors for this file.\n Names of the original copyright holders (individuals or organizations)\n should be listed with a '*' in the first column. People who have\n contributed from an organization can be listed under the organization\n that actually holds the copyright for their contributions (see the\n Mojaloop Foundation for an example). Those individuals should have\n their names indented and be marked with a '-'. Email address can be added\n optionally within square brackets <email>.\n\n * Mojaloop Foundation\n - Name Surname <name.surname@mojaloop.io>\n\n * Eugen Klymniuk <eugen.klymniuk@infitx.com>\n --------------\n **********/\n\n/**\n * We need a separate validation, coz the library might be used in JS projects, where TS type checks are not available\n */\nimport Ajv, { JSONSchemaType } from 'ajv';\nimport { PropertiesSchema } from 'ajv/dist/types/json-schema';\nimport {\n RedisProxyCacheConfig,\n RedisOptions,\n RedisClusterProxyCacheConfig,\n RedisClusterOptions,\n BasicConnectionConfig,\n AlsRequestDetails,\n} from './types';\nimport { ValidationError } from '../src/lib';\n\nconst ajv = new Ajv();\n\nconst BasicConnectionSchema: JSONSchemaType<BasicConnectionConfig> = {\n type: 'object',\n properties: {\n host: { type: 'string', minLength: 1 },\n port: { type: 'integer' },\n },\n required: ['host', 'port'],\n additionalProperties: false,\n};\n\nconst RedisOptionsSchema: JSONSchemaType<RedisOptions> = {\n type: 'object',\n properties: {\n username: { type: 'string', nullable: true },\n password: { type: 'string', nullable: true },\n lazyConnect: { type: 'boolean', nullable: true },\n db: { type: 'number', nullable: true },\n },\n additionalProperties: true,\n};\n\nconst RedisProxyCacheConfigSchema: JSONSchemaType<RedisProxyCacheConfig> = {\n type: 'object',\n properties: {\n ...(BasicConnectionSchema.properties as PropertiesSchema<BasicConnectionConfig>),\n ...(RedisOptionsSchema.properties as PropertiesSchema<RedisOptions>),\n },\n required: ['host', 'port'],\n additionalProperties: true,\n};\nconst redisProxyCacheConfigValidatingFn = ajv.compile<RedisProxyCacheConfig>(RedisProxyCacheConfigSchema);\n\nexport const validateRedisProxyCacheConfig = (cacheConfig: unknown): RedisProxyCacheConfig => {\n const isValid = redisProxyCacheConfigValidatingFn(cacheConfig);\n if (!isValid) {\n const errDetails = `redisProxyCacheConfig error: ${redisProxyCacheConfigValidatingFn.errors![0]!.message}`;\n throw ValidationError.invalidFormat(errDetails);\n }\n return cacheConfig;\n};\n\nconst RedisClusterProxyCacheConfigSchema: JSONSchemaType<RedisClusterProxyCacheConfig> = {\n type: 'object',\n properties: {\n cluster: { type: 'array', items: BasicConnectionSchema, minItems: 1 },\n ...(RedisOptionsSchema.properties as PropertiesSchema<RedisClusterOptions>),\n },\n required: ['cluster'],\n additionalProperties: true,\n};\nconst redisClusterProxyCacheConfigValidatingFn = ajv.compile<RedisClusterProxyCacheConfig>(\n RedisClusterProxyCacheConfigSchema,\n);\n\nexport const validateRedisClusterProxyCacheConfig = (cacheConfig: unknown): RedisClusterProxyCacheConfig => {\n const isValid = redisClusterProxyCacheConfigValidatingFn(cacheConfig);\n if (!isValid) {\n const errDetails = `redisClusterProxyCacheConfig error: ${redisClusterProxyCacheConfigValidatingFn.errors![0]!.message}`;\n throw ValidationError.invalidFormat(errDetails);\n }\n return cacheConfig;\n};\n\nconst AlsRequestSchema: JSONSchemaType<AlsRequestDetails> = {\n type: 'object',\n properties: {\n sourceId: { type: 'string' },\n type: { type: 'string' },\n partyId: { type: 'string' },\n },\n required: ['sourceId', 'type', 'partyId'],\n additionalProperties: false,\n};\nconst alsRequestValidatingFn = ajv.compile<AlsRequestDetails>(AlsRequestSchema);\n\nexport const validateAlsRequestDetails = (data: unknown): true => {\n const isValid = alsRequestValidatingFn(data);\n if (!isValid) {\n const errDetails = `alsRequest: ${alsRequestValidatingFn.errors![0]!.message}`;\n throw ValidationError.invalidFormat(errDetails);\n // think, if we need to throw or just return false?\n }\n return true;\n};\n\nconst DfspIdSchema: JSONSchemaType<string> = {\n type: 'string',\n minLength: 1,\n maxLength: 32,\n};\nconst dfspIdValidatingFn = ajv.compile<string>(DfspIdSchema);\n\nexport const validateDfspId = (data: unknown): true => {\n const isValid = dfspIdValidatingFn(data);\n if (!isValid) {\n const errDetails = `dfspId: ${dfspIdValidatingFn.errors![0]!.message}`;\n throw ValidationError.invalidFormat(errDetails);\n // think, if we need to throw or just return false?\n }\n return true;\n};\n","import Redis, { Cluster } from 'ioredis';\n\nimport * as validation from '../../validation';\nimport config from '../../config';\nimport { logger } from '../../utils';\nimport {\n IProxyCache,\n RedisProxyCacheConfig,\n RedisClusterProxyCacheConfig,\n RedisConnectionStatus,\n IsLastFailure,\n AlsRequestDetails,\n ILogger,\n ProcessExpiryKeyCallback,\n ProcessNodeStreamSingleKeyCallback,\n} from '../../types';\nimport { REDIS_KEYS_PREFIXES, REDIS_SUCCESS, REDIS_IS_CONNECTED_STATUSES } from './constants';\n\nconst PROCESS_NODE_STREAM_TIMEOUT_MS = 2 * 60 * 1000; // todo: make configurable\n\ntype RedisClient = Redis | Cluster;\ntype RedisConfig = RedisProxyCacheConfig | RedisClusterProxyCacheConfig;\ntype ProcessNodeOptions = {\n pattern: string;\n batchSize: number;\n callbackFn: ProcessExpiryKeyCallback;\n resolve: (...args: any[]) => void;\n reject: (reason?: Error) => void;\n};\n\ntype NodeStreamOptions = {\n pattern: string;\n batchSize: number;\n};\n\nconst isClusterConfig = (config: RedisConfig, isCluster: boolean): config is RedisClusterProxyCacheConfig => isCluster;\n\nexport class RedisProxyCache implements IProxyCache {\n private readonly redisClient: RedisClient;\n private readonly log: ILogger;\n private readonly defaultTtlSec = config.get('defaultTtlSec');\n private isCluster = false;\n\n constructor(\n private readonly proxyConfig: RedisConfig,\n isCluster: boolean = false,\n ) {\n isClusterConfig(proxyConfig, isCluster);\n this.isCluster = isCluster;\n this.log = logger.child({ component: this.constructor.name });\n this.redisClient = this.createRedisClient();\n }\n\n protected get redisNodes() {\n // prettier-ignore\n return this.isCluster\n ? (this.redisClient as Cluster).nodes('master')\n : [this.redisClient as Redis];\n }\n\n async addDfspIdToProxyMapping(dfspId: string, proxyId: string): Promise<boolean> {\n const key = RedisProxyCache.formatDfspCacheKey(dfspId);\n const response = await this.redisClient.set(key, proxyId);\n const isAdded = response === REDIS_SUCCESS;\n this.log.debug('proxyMapping is added', { key, proxyId, isAdded });\n return isAdded;\n }\n\n async lookupProxyByDfspId(dfspId: string): Promise<string | null> {\n const key = RedisProxyCache.formatDfspCacheKey(dfspId);\n const proxyId = await this.redisClient.get(key);\n this.log.debug('lookupProxyByDfspId is done', { key, proxyId });\n return proxyId;\n }\n\n async removeDfspIdFromProxyMapping(dfspId: string): Promise<boolean> {\n const key = RedisProxyCache.formatDfspCacheKey(dfspId);\n const result = await this.redisClient.del(key);\n const isRemoved = result === 1;\n this.log.debug('proxyMapping is removed', { key, isRemoved, result });\n return isRemoved;\n }\n\n async removeProxyGetPartiesTimeout(alsReq: AlsRequestDetails, proxyId: string): Promise<boolean> {\n const key = RedisProxyCache.formatProxyGetPartiesExpiryKey(alsReq, proxyId);\n const result = await this.redisClient.del(key);\n this.log.debug('removeProxyGetPartiesTimeout is done', { result, key });\n return result > 0;\n }\n\n async setProxyGetPartiesTimeout(\n alsReq: AlsRequestDetails,\n proxyId: string,\n ttlSec: number = this.defaultTtlSec,\n ): Promise<boolean> {\n const key = RedisProxyCache.formatProxyGetPartiesExpiryKey(alsReq, proxyId);\n const expiryTime = Date.now() + ttlSec * 1000;\n const result = await this.redisClient.set(key, expiryTime);\n this.log.debug('setProxyGetPartiesTimeout is done', { result, key, expiryTime });\n return result === REDIS_SUCCESS;\n }\n\n async setSendToProxiesList(alsReq: AlsRequestDetails, proxyIds: string[], ttlSec: number): Promise<boolean> {\n const key = RedisProxyCache.formatAlsCacheKey(alsReq);\n const expiryKey = RedisProxyCache.formatAlsCacheExpiryKey(alsReq);\n\n const isExists = await this.redisClient.exists(key);\n if (isExists) {\n this.log.warn('sendToProxiesList already exists', { key });\n return false;\n }\n\n const uniqueProxyIds = [...new Set(proxyIds)];\n const ttl = ttlSec ?? this.defaultTtlSec;\n const expiryTime = Date.now() + ttl * 1000;\n let isOk;\n if (this.isCluster) {\n // pipeline is not supported in cluster mode for multi-key operations\n const [addedCount, expirySetResult] = await Promise.all([\n this.redisClient.sadd(key, uniqueProxyIds),\n this.redisClient.set(expiryKey, expiryTime),\n ]);\n isOk = addedCount === uniqueProxyIds.length && expirySetResult === REDIS_SUCCESS;\n } else {\n const [addedCount] = await this.executePipeline([\n ['sadd', key, ...uniqueProxyIds],\n ['set', expiryKey, expiryTime],\n ]);\n isOk = addedCount === uniqueProxyIds.length;\n }\n\n this.log.verbose('setSendToProxiesList is done', { isOk, key, uniqueProxyIds, ttl });\n return isOk;\n }\n\n async receivedSuccessResponse(alsReq: AlsRequestDetails): Promise<boolean> {\n const key = RedisProxyCache.formatAlsCacheKey(alsReq);\n const expiryKey = RedisProxyCache.formatAlsCacheExpiryKey(alsReq);\n let isDeleted;\n let logMeta;\n if (this.isCluster) {\n const [delResult, delExpiryResult] = await Promise.all([\n this.redisClient.del(key),\n this.redisClient.del(expiryKey),\n ]);\n isDeleted = delResult === 1 && delExpiryResult === 1;\n logMeta = { isDeleted, delResult, delExpiryResult };\n } else {\n const delResult = await this.executePipeline([\n ['del', key],\n ['del', expiryKey],\n ]);\n isDeleted = delResult[0] === 1 && delResult[1] === 1;\n logMeta = { isDeleted, delResult };\n }\n this.log.debug('sendToProxiesList is deleted', logMeta);\n return isDeleted;\n }\n\n async receivedErrorResponse(alsReq: AlsRequestDetails, proxyId: string): Promise<IsLastFailure> {\n const key = RedisProxyCache.formatAlsCacheKey(alsReq);\n const expiryKey = RedisProxyCache.formatAlsCacheExpiryKey(alsReq);\n\n const [delCount, card] = await this.executePipeline([\n ['srem', key, proxyId],\n ['scard', key],\n ]);\n\n const isLast = delCount === 1 && card === 0;\n\n if (isLast) {\n const [delKeyCount, delExpiryCount] = await Promise.all([\n this.redisClient.del(key),\n this.redisClient.del(expiryKey),\n ]);\n this.log.info('receivedErrorResponse: last response received, keys were deleted', {\n isLast,\n delKeyCount,\n delExpiryCount,\n });\n }\n\n this.log.info('receivedErrorResponse is done', { isLast, alsReq, delCount, card });\n return isLast;\n }\n\n async isPendingCallback(alsReq: AlsRequestDetails): Promise<boolean> {\n const key = RedisProxyCache.formatAlsCacheKey(alsReq);\n const card = await this.redisClient.scard(key);\n this.log.debug('isPendingCallbacks for alsReq is done', { key, card });\n return card > 0;\n }\n\n // todo: refactor to use processAllNodesStream\n async processExpiredAlsKeys(callbackFn: ProcessExpiryKeyCallback, batchSize: number): Promise<unknown> {\n const pattern = RedisProxyCache.formatAlsCacheExpiryKey({ sourceId: '*', type: '*', partyId: '*' });\n\n return Promise.all(\n this.redisNodes.map(async (node) => {\n return new Promise((resolve, reject) => {\n this.processNode(node, { pattern, batchSize, callbackFn, resolve, reject });\n });\n }),\n );\n }\n\n // prettier-ignore\n async processExpiredProxyGetPartiesKeys(customFn: ProcessNodeStreamSingleKeyCallback, batchSize: number): Promise<unknown> {\n const pattern = RedisProxyCache.formatProxyGetPartiesExpiryKey({ sourceId: '*', type: '*', partyId: '*' }, '*');\n\n return this.processAllNodesStream({ pattern, batchSize }, async (key: string) => {\n const result = await Promise.all([\n customFn(key.replace(':expiresAt', '')).catch((err) => {\n this.log.warn(`error processing expired proxyGetParties key ${key} - `, err);\n return err; // or is it better to throw here?\n }),\n this.redisClient.del(key),\n ]);\n this.log.verbose('processExpiredProxyGetPartiesKeys is done', { result });\n return result;\n });\n }\n\n async connect(): Promise<RedisConnectionStatus> {\n if (this.isConnected) {\n const { status } = this.redisClient;\n this.log.warn('proxyCache is already connected', { status });\n return status;\n }\n await this.redisClient.connect();\n const { status } = this.redisClient;\n this.log.info('proxyCache is connected', { status });\n return status;\n }\n\n async disconnect(): Promise<boolean> {\n const response = await this.redisClient.quit();\n const isDisconnected = response === REDIS_SUCCESS;\n this.redisClient.removeAllListeners();\n this.log.info('proxyCache is disconnected', { isDisconnected, response });\n return isDisconnected;\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n const response = await this.redisClient.ping();\n const isHealthy = response === 'PONG';\n this.log.debug('healthCheck ping response', { isHealthy, response });\n return isHealthy;\n } catch (err: unknown) {\n this.log.warn('healthCheck error', err);\n return false;\n }\n }\n\n get isConnected(): boolean {\n const isConnected = REDIS_IS_CONNECTED_STATUSES.includes(this.redisClient.status);\n this.log.debug('isConnected', { isConnected });\n return isConnected;\n }\n\n private createRedisClient() {\n this.proxyConfig.lazyConnect ??= true;\n // prettier-ignore\n const redisClient = isClusterConfig(this.proxyConfig, this.isCluster)\n ? new Cluster(this.proxyConfig.cluster, this.proxyConfig)\n : new Redis(this.proxyConfig);\n\n this.addEventListeners(redisClient);\n return redisClient;\n }\n\n private addEventListeners(redisClient: RedisClient) {\n const { log } = this;\n // prettier-ignore\n redisClient\n .on('error', (err) => { log.error('redis connection error', err); })\n .on('close', () => { log.info('redis connection closed'); })\n .on('end', () => { log.warn('redis connection ended'); })\n .on('reconnecting', (ms: number) => { log.info('redis connection reconnecting', { ms }); })\n .on('connect', () => { log.verbose('redis connection is established'); })\n .on('ready', () => { log.verbose('redis connection is ready'); });\n }\n\n private async executePipeline(commands: [string, ...any[]][]): Promise<unknown[]> {\n const pipeline = this.redisClient.pipeline();\n\n commands.forEach(([command, ...args]) => {\n // @ts-expect-error TS7052: Element implicitly has an any type because type ChainableCommander has no index signature\n if (typeof pipeline[command] === 'function') pipeline[command](...args);\n else this.log.warn('unknown redis command', { command, args });\n });\n\n try {\n const results = await pipeline.exec();\n if (!results) {\n throw new Error('no pipeline results');\n }\n return results.map((result, index) => {\n if (result[0]) {\n const errMessage = `error in command ${index + 1}: ${result[0].message}`;\n this.log.warn(errMessage, result[0]);\n // todo: think, if we need to \"undo\" successful commands, if they finished before the error\n throw new Error(errMessage);\n }\n return result[1];\n });\n } catch (error: unknown) {\n this.log.error('pipeline execution failed', error);\n return [];\n }\n }\n\n /** @deprecated Use processAllNodesStream */\n private async processNode(node: Redis, options: ProcessNodeOptions): Promise<void> {\n const { pattern: match, batchSize: count, callbackFn, resolve, reject } = options;\n const stream = node.scanStream({ match, count });\n\n stream.on('data', async (keys) => {\n stream.pause();\n try {\n await Promise.all(keys.map((key: string) => this.processExpiryKey(key, callbackFn)));\n } catch (err: unknown) {\n stream.destroy(err as Error);\n reject(err as Error);\n }\n stream.resume();\n });\n stream.on('end', resolve);\n }\n\n private async processAllNodesStream(options: NodeStreamOptions, callbackFn: ProcessNodeStreamSingleKeyCallback) {\n const result = await Promise.all(\n this.redisNodes.map((node) => this.processSingleNodeStream(node, options, callbackFn)),\n );\n this.log.debug('processAllNodesStream is done', { result });\n return result;\n }\n\n private async processSingleNodeStream(\n node: Redis,\n options: NodeStreamOptions,\n processKeyFn: ProcessNodeStreamSingleKeyCallback,\n ): Promise<unknown> {\n const { pattern: match, batchSize: count } = options;\n\n return new Promise((resolve, reject) => {\n const stream = node.scanStream({ match, count });\n let result: unknown;\n\n let timer: ReturnType<typeof setTimeout> | null = setTimeout(() => {\n const err = new Error(`Timeout during processNodeStream [${PROCESS_NODE_STREAM_TIMEOUT_MS} ms]`);\n stream.destroy(err);\n reject(err);\n }, PROCESS_NODE_STREAM_TIMEOUT_MS);\n const clearTimer = () => {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n };\n\n stream.on('data', async (keys) => {\n stream.pause();\n try {\n result = await Promise.all(keys.map(processKeyFn));\n } catch (err: unknown) {\n this.log.warn('error in processNodeStream data: ', err);\n clearTimer();\n stream.destroy(err as Error);\n reject(err);\n }\n stream.resume();\n });\n stream.on('end', () => {\n this.log.debug('processNodeStream is done', { result });\n clearTimer();\n resolve(result);\n });\n stream.on('error', (err) => {\n this.log.warn('processNodeStream stream error: ', err);\n clearTimer();\n reject(err);\n });\n });\n }\n\n private async processExpiryKey(expiryKey: string, callbackFn: ProcessExpiryKeyCallback): Promise<any> {\n const actualKey = expiryKey.replace(':expiresAt', '');\n const expiresAt = await this.redisClient.get(expiryKey);\n\n if (Number(expiresAt) >= Date.now()) return;\n\n // prettier-ignore\n const deleteKeys = this.isCluster\n ? () => Promise.all([this.redisClient.del(actualKey), this.redisClient.del(expiryKey)])\n : () => this.executePipeline([['del', actualKey], ['del', expiryKey]]);\n\n return Promise.all([\n callbackFn(actualKey).catch((err) => {\n this.log.warn(`processExpiryKey callback error ${expiryKey}`, err);\n return Promise.resolve();\n }),\n deleteKeys().catch((err) => {\n this.log.error(`processExpiryKey key deletion error ${expiryKey}`, err);\n return Promise.reject(err);\n }),\n ]);\n }\n\n static formatAlsCacheKey(alsReq: AlsRequestDetails): string {\n validation.validateAlsRequestDetails(alsReq);\n return `${REDIS_KEYS_PREFIXES.als}:${alsReq.sourceId}:${alsReq.type}:${alsReq.partyId}`;\n }\n\n static formatAlsCacheExpiryKey(alsReq: AlsRequestDetails): string {\n return `${RedisProxyCache.formatAlsCacheKey(alsReq)}:expiresAt`;\n }\n\n static formatProxyGetPartiesExpiryKey(alsReq: AlsRequestDetails, proxyId: string): string {\n return `${REDIS_KEYS_PREFIXES.getParties}:${proxyId}:${alsReq.sourceId}:${alsReq.type}:${alsReq.partyId}:expiresAt`;\n }\n\n static formatDfspCacheKey(dfspId: string): string {\n validation.validateDfspId(dfspId);\n return `${REDIS_KEYS_PREFIXES.dfsp}:${dfspId}`;\n }\n}\n","/*****\n License\n --------------\n Copyright © 2020-2025 Mojaloop Foundation\n The Mojaloop files are made available by the Mojaloop 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\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n 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.\n\n Contributors\n --------------\n This is the official list of the Mojaloop project contributors for this file.\n Names of the original copyright holders (individuals or organizations)\n should be listed with a '*' in the first column. People who have\n contributed from an organization can be listed under the organization\n that actually holds the copyright for their contributions (see the\n Mojaloop Foundation for an example). Those individuals should have\n their names indented and be marked with a '-'. Email address can be added\n optionally within square brackets <email>.\n\n * Mojaloop Foundation\n - Name Surname <name.surname@mojaloop.io>\n\n * Eugen Klymniuk <eugen.klymniuk@infitx.com>\n --------------\n **********/\n\nimport { ProxyCacheFactory, StorageType, ProxyCacheConfig } from '../types';\nimport { validateRedisClusterProxyCacheConfig, validateRedisProxyCacheConfig } from '../validation';\nimport { logger } from '../utils';\nimport { STORAGE_TYPES } from '../constants';\nimport { ProxyCacheError } from './errors';\nimport * as storages from './storages';\n\nexport const createProxyCache: ProxyCacheFactory = (type: StorageType, proxyConfig: ProxyCacheConfig) => {\n switch (type) {\n case STORAGE_TYPES.redis: {\n return new storages.RedisProxyCache(validateRedisProxyCacheConfig(proxyConfig));\n }\n case STORAGE_TYPES.redisCluster: {\n return new storages.RedisProxyCache(validateRedisClusterProxyCacheConfig(proxyConfig), true);\n }\n case STORAGE_TYPES.mysql:\n throw new Error('Mysql storage is not implemented yet');\n default: {\n const error = ProxyCacheError.unsupportedProxyCacheType();\n logger.warn(error.message, proxyConfig);\n throw error;\n }\n }\n};\n"],"mappings":"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","names":["status"]}