UNPKG

@mojaloop/inter-scheme-proxy-cache-lib

Version:

Common component, that provides scheme proxy caching mapping (ISPC)

1 lines 38.9 kB
{"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 readonly isCluster: boolean = 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 = this.calculateExpiryTimestampInMs(ttlSec);\n const result = await this.redisClient.set(key, expiryTime);\n this.log.verbose('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 expiryTime = this.calculateExpiryTimestampInMs(ttlSec);\n let isOk;\n\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, expiryTime });\n return isOk;\n }\n\n async receivedSuccessResponse(alsReq: AlsRequestDetails, proxyId: string): Promise<boolean> {\n const isPending = await this.isPendingCallback(alsReq, proxyId);\n if (!isPending) {\n this.log.verbose('receivedSuccessResponse is skipped (not ISDf)', { isPending, alsReq, proxyId });\n return false;\n }\n\n const isSet = await this.storeSuccessAlsResponse(alsReq, proxyId);\n const { isLast } = await this.isLastCallback(alsReq, proxyId);\n\n this.log.info('receivedSuccessResponse is done', { isLast, isSet, alsReq, proxyId });\n return isSet;\n }\n\n async receivedErrorResponse(alsReq: AlsRequestDetails, proxyId: string): Promise<IsLastFailure> {\n const { isLast, card, hadSuccess } = await this.isLastCallback(alsReq, proxyId);\n const isLastWithoutSuccess = isLast && !hadSuccess;\n this.log.info('receivedErrorResponse is done', { isLast, isLastWithoutSuccess, alsReq, card, proxyId });\n return isLastWithoutSuccess;\n }\n\n async isPendingCallback(alsReq: AlsRequestDetails, proxyId: string = ''): Promise<boolean> {\n if (!proxyId) return false;\n const key = RedisProxyCache.formatAlsCacheKey(alsReq);\n const isMember = await this.redisClient.sismember(key, proxyId);\n this.log.verbose('isPendingCallback for alsReq is done', { key, isMember, proxyId });\n return isMember === 1;\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 results from pipeline.exec()');\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 // 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.info('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.info('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 // todo: add tests for successKey case\n private async processExpiryKey(expiryKey: string, callbackFn: ProcessExpiryKeyCallback): Promise<unknown> {\n const expiresAt = await this.redisClient.get(expiryKey);\n if (Number(expiresAt) >= Date.now()) return;\n\n const actualKey = expiryKey.replace(':expiresAt', '');\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 const alsReq = RedisProxyCache.extractAlsRequestDetails(expiryKey);\n const successKey = RedisProxyCache.formatAlsCacheSuccessKey(alsReq);\n const proxyId = await this.redisClient.get(successKey);\n\n const jobs = [\n deleteKeys().catch((err) => {\n this.log.error(`processExpiryKey key deletion error ${expiryKey}: `, err);\n return err;\n }),\n ];\n\n if (!proxyId) {\n // no success callback\n jobs.push(\n callbackFn(actualKey).catch((err) => {\n this.log.warn(`processExpiryKey callbackFn error ${expiryKey}: `, err);\n return err;\n }),\n );\n } else {\n this.log.info('expired ALS request has success callback', { alsReq, expiryKey, proxyId });\n jobs.push(\n this.redisClient.del(successKey).catch((err) => {\n this.log.warn(`processExpiryKey delete successKey error: `, err);\n return err;\n }),\n );\n }\n\n return Promise.all(jobs);\n }\n\n private async storeSuccessAlsResponse(alsReq: AlsRequestDetails, proxyId: string): Promise<boolean> {\n const key = RedisProxyCache.formatAlsCacheSuccessKey(alsReq);\n const response = await this.redisClient.set(key, proxyId);\n const isSet = response === REDIS_SUCCESS;\n this.log.info('storeSuccessAlsResponse is done', { key, proxyId, isSet });\n return isSet;\n }\n\n // prettier-ignore\n private async isLastCallback(alsReq: AlsRequestDetails, proxyId: string): Promise<{\n isLast: boolean;\n key: string;\n card: unknown; // cardinality (number of elements) of the set\n hadSuccess: boolean; // if success callback was received during the inter-scheme discovery flow\n }> {\n const key = RedisProxyCache.formatAlsCacheKey(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 let hadSuccess = false;\n\n if (isLast) {\n const [delKeyCount, delExpiryCount, delSuccessCount] = await Promise.all([\n this.redisClient.del(key),\n this.redisClient.del(RedisProxyCache.formatAlsCacheExpiryKey(alsReq)),\n this.redisClient.del(RedisProxyCache.formatAlsCacheSuccessKey(alsReq)),\n ]);\n this.log.verbose('received last callback, keys were deleted', { delKeyCount, delExpiryCount, delSuccessCount });\n hadSuccess = delSuccessCount === 1;\n }\n\n const result = {\n isLast, hadSuccess, key, card,\n }\n this.log.info('isLastCallback is done:', result);\n return result;\n }\n\n private calculateExpiryTimestampInMs(ttlSec: number = this.defaultTtlSec): number {\n if (typeof ttlSec === 'number' && ttlSec > 0) {\n return Date.now() + ttlSec * 1000;\n }\n throw new Error(`Invalid TTL value: ${ttlSec}. Expected a positive number`);\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 formatAlsCacheSuccessKey(alsReq: AlsRequestDetails): string {\n return `${RedisProxyCache.formatAlsCacheKey(alsReq)}:success`;\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 static extractAlsRequestDetails(key: string): AlsRequestDetails {\n const [prefix, sourceId, type, partyId] = key.split(':');\n\n if (!prefix || !(prefix in REDIS_KEYS_PREFIXES)) {\n throw new Error(`Invalid key prefix: ${prefix}`);\n }\n if (!sourceId || !type || !partyId) {\n throw new Error(`No required ALS request details extracted from cache key ${key}!`);\n }\n\n return { sourceId, type, partyId };\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"]}