diff --git a/docs/testing-guide.md b/docs/testing-guide.md index c88efe845a..1a2c31afa9 100644 --- a/docs/testing-guide.md +++ b/docs/testing-guide.md @@ -156,6 +156,7 @@ import chaiAsPromised from 'chai-as-promised'; import sinon from 'sinon'; import { MyClass } from './my-class'; import { CacheService } from './cache-service'; +import { CacheClientFactory } from './cacheClientFactory'; chai.use(chaiAsPromised); @@ -165,7 +166,7 @@ describe('MyClass', function() { beforeEach(function() { // Common setup for all tests - cacheService = new CacheService(); + cacheService = CacheClientFactory.create(); myClass = new MyClass(cacheService); }); @@ -229,7 +230,7 @@ describe('MyClass', function() { }); }); }); - + describe('anotherMethod', () => { // Tests for anotherMethod // Use analogous formatting to the tests for myMethod @@ -289,7 +290,7 @@ describe('MyClass', function() { beforeEach(function() { // Common setup for all tests serviceThatDependsOnEnv = new ServiceThatDependsOnEnv(); - cacheService = new CacheService(); + cacheService = CacheClientFactory.create(); myClass = new MyClass(serviceThatDependsOnEnv, cacheService); }); diff --git a/packages/relay/src/lib/clients/cache/ICacheClient.ts b/packages/relay/src/lib/clients/cache/ICacheClient.ts index 4590c3877b..505071b980 100644 --- a/packages/relay/src/lib/clients/cache/ICacheClient.ts +++ b/packages/relay/src/lib/clients/cache/ICacheClient.ts @@ -4,8 +4,16 @@ export interface ICacheClient { keys(pattern: string, callingMethod: string): Promise; get(key: string, callingMethod: string): Promise; set(key: string, value: any, callingMethod: string, ttl?: number): Promise; - multiSet(keyValuePairs: Record, callingMethod: string): Promise; + multiSet(keyValuePairs: Record, callingMethod: string, ttl?: number | undefined): Promise; pipelineSet(keyValuePairs: Record, callingMethod: string, ttl?: number | undefined): Promise; delete(key: string, callingMethod: string): Promise; clear(): Promise; + incrBy(key: string, amount: number, callingMethod: string): Promise; + rPush(key: string, value: any, callingMethod: string): Promise; + lRange(key: string, start: number, end: number, callingMethod: string): Promise; + + /** + * @deprecated Alias of `get`; consider removing. Left in place to avoid modifying the CacheService interface. + */ + getAsync(key: string, callingMethod: string): Promise; } diff --git a/packages/relay/src/lib/clients/cache/IRedisCacheClient.ts b/packages/relay/src/lib/clients/cache/IRedisCacheClient.ts deleted file mode 100644 index 59a1ae3176..0000000000 --- a/packages/relay/src/lib/clients/cache/IRedisCacheClient.ts +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -import { RequestDetails } from '../../types'; -import type { ICacheClient } from './ICacheClient'; - -export interface IRedisCacheClient extends ICacheClient { - incrBy(key: string, amount: number, callingMethod: string, requestDetails: RequestDetails): Promise; - rPush(key: string, value: any, callingMethod: string, requestDetails: RequestDetails): Promise; - lRange( - key: string, - start: number, - end: number, - callingMethod: string, - requestDetails: RequestDetails, - ): Promise; -} diff --git a/packages/relay/src/lib/clients/cache/localLRUCache.ts b/packages/relay/src/lib/clients/cache/localLRUCache.ts index 63cf309b49..6bb6787d9c 100644 --- a/packages/relay/src/lib/clients/cache/localLRUCache.ts +++ b/packages/relay/src/lib/clients/cache/localLRUCache.ts @@ -72,6 +72,7 @@ export class LocalLRUCache implements ICacheClient { * @constructor * @param {Logger} logger - The logger instance to be used for logging. * @param {Registry} register - The registry instance used for metrics tracking. + * @param {Set} reservedKeys - These are the cache keys delegated to the reserved cache. */ public constructor(logger: Logger, register: Registry, reservedKeys: Set = new Set()) { this.cache = new LRUCache(this.options); @@ -109,6 +110,19 @@ export class LocalLRUCache implements ICacheClient { return `${LocalLRUCache.CACHE_KEY_PREFIX}${key}`; } + /** + * Alias for the `get` method. + * + * @param key - The key associated with the cached value. + * @param callingMethod - The name of the method calling the cache. + * @returns The cached value if found, otherwise null. + * + * @deprecated use `get` instead. + */ + public getAsync(key: string, callingMethod: string): Promise { + return this.get(key, callingMethod); + } + /** * Retrieves a cached value associated with the given key. * If the value exists in the cache, updates metrics and logs the retrieval. @@ -137,8 +151,9 @@ export class LocalLRUCache implements ICacheClient { * @param key - The key to check the remaining TTL for. * @param callingMethod - The name of the method calling the cache. * @returns The remaining TTL in milliseconds. + * @private */ - public async getRemainingTtl(key: string, callingMethod: string): Promise { + private async getRemainingTtl(key: string, callingMethod: string): Promise { const prefixedKey = this.prefixKey(key); const cache = this.getCacheInstance(key); const remainingTtl = cache.getRemainingTTL(prefixedKey); // in milliseconds @@ -280,6 +295,70 @@ export class LocalLRUCache implements ICacheClient { return matchingKeys.map((key) => key.substring(LocalLRUCache.CACHE_KEY_PREFIX.length)); } + /** + * Increments a value in the cache. + * + * @param key The key to increment + * @param amount The amount to increment by + * @param callingMethod The name of the calling method + * @returns The value of the key after incrementing + */ + public async incrBy(key: string, amount: number, callingMethod: string): Promise { + const value = await this.get(key, callingMethod); + const newValue = value + amount; + const remainingTtl = await this.getRemainingTtl(key, callingMethod); + await this.set(key, newValue, callingMethod, remainingTtl); + return newValue; + } + + /** + * Retrieves a range of elements from a list in the cache. + * + * @param key The key of the list + * @param start The start index + * @param end The end index + * @param callingMethod The name of the calling method + * @returns The list of elements in the range + */ + public async lRange(key: string, start: number, end: number, callingMethod: string): Promise { + const values = (await this.get(key, callingMethod)) ?? []; + if (!Array.isArray(values)) { + throw new Error(`Value at key ${key} is not an array`); + } + if (end < 0) { + end = values.length + end; + } + return values.slice(start, end + 1); + } + + /** + * Pushes a value to the end of a list in the cache. + * + * @param key The key of the list + * @param value The value to push + * @param callingMethod The name of the calling method + * @returns The length of the list after pushing + */ + public async rPush(key: string, value: any, callingMethod: string): Promise { + const values = (await this.get(key, callingMethod)) ?? []; + if (!Array.isArray(values)) { + throw new Error(`Value at key ${key} is not an array`); + } + values.push(value); + const remainingTtl = await this.getRemainingTtl(key, callingMethod); + await this.set(key, values, callingMethod, remainingTtl); + return values.length; + } + + /** + * Returns the appropriate cache instance for the given key. + * If a reserved cache exists and the key is marked as reserved, + * the reserved cache is returned; otherwise the default cache is used. + * + * @param key - The cache key being accessed. + * @returns The selected cache instance + * @private + */ private getCacheInstance(key: string): LRUCache { return this.reservedCache && this.reservedKeys.has(key) ? this.reservedCache : this.cache; } diff --git a/packages/relay/src/lib/clients/cache/redisCache.ts b/packages/relay/src/lib/clients/cache/redisCache.ts index 7238343cb0..7e0329bb17 100644 --- a/packages/relay/src/lib/clients/cache/redisCache.ts +++ b/packages/relay/src/lib/clients/cache/redisCache.ts @@ -2,16 +2,15 @@ import { ConfigService } from '@hashgraph/json-rpc-config-service/dist/services'; import { Logger } from 'pino'; -import { Registry } from 'prom-client'; import { RedisClientType } from 'redis'; import { Utils } from '../../../utils'; -import { IRedisCacheClient } from './IRedisCacheClient'; +import { ICacheClient } from './ICacheClient'; /** * A class that provides caching functionality using Redis. */ -export class RedisCache implements IRedisCacheClient { +export class RedisCache implements ICacheClient { /** * Prefix used to namespace all keys managed by this cache. * @@ -29,6 +28,7 @@ export class RedisCache implements IRedisCacheClient { private readonly options = { // Max time to live in ms, for items before they are considered stale. ttl: ConfigService.get('CACHE_TTL'), + multiSetEnabled: ConfigService.get('MULTI_SET'), }; /** @@ -37,12 +37,6 @@ export class RedisCache implements IRedisCacheClient { */ private readonly logger: Logger; - /** - * The metrics register used for metrics tracking. - * @private - */ - private readonly register: Registry; - /** * The Redis client. * @private @@ -53,11 +47,10 @@ export class RedisCache implements IRedisCacheClient { * Creates an instance of `RedisCache`. * * @param {Logger} logger - The logger instance. - * @param {Registry} register - The metrics registry. + * @param {RedisClientType} client */ - public constructor(logger: Logger, register: Registry, client: RedisClientType) { + public constructor(logger: Logger, client: RedisClientType) { this.logger = logger; - this.register = register; this.client = client; } @@ -72,6 +65,19 @@ export class RedisCache implements IRedisCacheClient { return `${RedisCache.CACHE_KEY_PREFIX}${key}`; } + /** + * Alias for the `get` method. + * + * @param key - The key associated with the cached value. + * @param callingMethod - The name of the method calling the cache. + * @returns The cached value if found, otherwise null. + * + * @deprecated use `get` instead. + */ + public getAsync(key: string, callingMethod: string): Promise { + return this.get(key, callingMethod); + } + /** * Retrieves a value from the cache. * @@ -88,7 +94,6 @@ export class RedisCache implements IRedisCacheClient { const censoredValue = result.replace(/"ipAddress":"[^"]+"/, '"ipAddress":""'); this.logger.trace(`Returning cached value ${censoredKey}:${censoredValue} on ${callingMethod} call`); } - // TODO: add metrics return JSON.parse(result); } return null; @@ -129,9 +134,11 @@ export class RedisCache implements IRedisCacheClient { * * @param keyValuePairs - An object where each property is a key and its value is the value to be cached. * @param callingMethod - The name of the calling method. + * @param [ttl] - The time-to-live (expiration) of the cache item in milliseconds. Used in fallback to pipelineSet. * @returns A Promise that resolves when the values are cached. */ - async multiSet(keyValuePairs: Record, callingMethod: string): Promise { + async multiSet(keyValuePairs: Record, callingMethod: string, ttl?: number): Promise { + if (!this.options.multiSetEnabled) return this.pipelineSet(keyValuePairs, callingMethod, ttl); // Serialize values and add prefix const serializedKeyValuePairs: Record = {}; for (const [key, value] of Object.entries(keyValuePairs)) { diff --git a/packages/relay/src/lib/factories/cacheClientFactory.ts b/packages/relay/src/lib/factories/cacheClientFactory.ts new file mode 100644 index 0000000000..c8e63b85fb --- /dev/null +++ b/packages/relay/src/lib/factories/cacheClientFactory.ts @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 +import { ConfigService } from '@hashgraph/json-rpc-config-service/dist/services'; +import type { Logger } from 'pino'; +import { Registry } from 'prom-client'; +import { RedisClientType } from 'redis'; + +import { LocalLRUCache, RedisCache } from '../clients'; +import { ICacheClient } from '../clients/cache/ICacheClient'; +import { CacheService } from '../services/cacheService/cacheService'; + +export class CacheClientFactory { + static create( + logger: Logger, + register: Registry = new Registry(), + reservedKeys: Set = new Set(), + redisClient?: RedisClientType, + ): ICacheClient { + const local = new LocalLRUCache(logger.child({ name: 'localLRUCache' }), register, reservedKeys); + const redis = + !ConfigService.get('TEST') && redisClient !== undefined + ? new RedisCache(logger.child({ name: 'redisCache' }), redisClient!) + : undefined; + return new CacheService(logger, register, local, redis); + } +} diff --git a/packages/relay/src/lib/relay.ts b/packages/relay/src/lib/relay.ts index 2a250bed93..944f5e7429 100644 --- a/packages/relay/src/lib/relay.ts +++ b/packages/relay/src/lib/relay.ts @@ -19,6 +19,7 @@ import { IPAddressHbarSpendingPlanRepository } from './db/repositories/hbarLimit import { DebugImpl } from './debug'; import { RpcMethodDispatcher } from './dispatcher'; import { EthImpl } from './eth'; +import { CacheClientFactory } from './factories/cacheClientFactory'; import { NetImpl } from './net'; import { CacheService } from './services/cacheService/cacheService'; import HAPIService from './services/hapiService/hapiService'; @@ -283,7 +284,7 @@ export class Relay { const reservedKeys = HbarSpendingPlanConfigService.getPreconfiguredSpendingPlanKeys(this.logger); // Create CacheService with the connected Redis client (or undefined for LRU-only) - this.cacheService = new CacheService( + this.cacheService = CacheClientFactory.create( this.logger.child({ name: 'cache-service' }), this.register, reservedKeys, diff --git a/packages/relay/src/lib/services/cacheService/cacheService.ts b/packages/relay/src/lib/services/cacheService/cacheService.ts index 26dcd155a9..327865b562 100644 --- a/packages/relay/src/lib/services/cacheService/cacheService.ts +++ b/packages/relay/src/lib/services/cacheService/cacheService.ts @@ -1,23 +1,18 @@ // SPDX-License-Identifier: Apache-2.0 import { ConfigService } from '@hashgraph/json-rpc-config-service/dist/services'; -import type { Logger } from 'pino'; +import { Logger } from 'pino'; import { Counter, Registry } from 'prom-client'; -import { RedisClientType } from 'redis'; -import { LocalLRUCache, RedisCache } from '../../clients'; import { ICacheClient } from '../../clients/cache/ICacheClient'; import { RedisCacheError } from '../../errors/RedisCacheError'; -export enum CACHE_LEVEL { - L1 = 'L1_CACHE', - L2 = 'L2_CACHE', -} - /** - * A service that manages caching using different cache implementations based on configuration. + * Represents a LocalLRUCache instance that uses an LRU (Least Recently Used) caching strategy + * for caching items internally from requests. + * @implements {ICacheClient} */ -export class CacheService { +export class CacheService implements ICacheClient { /** * The LRU cache used for caching items from requests. * @@ -30,7 +25,7 @@ export class CacheService { * * @private */ - private readonly sharedCache: ICacheClient; + private readonly sharedCache?: ICacheClient; /** * The logger used for logging all output from this class. @@ -44,11 +39,6 @@ export class CacheService { */ private readonly register: Registry; - /** - * Used for reference to the state of REDIS_ENABLED and REDIS_URL env. variables. - */ - private readonly isSharedCacheEnabled: boolean; - /** * Used for setting what type of multiSet method should be used to save new values. */ @@ -82,21 +72,16 @@ export class CacheService { public constructor( logger: Logger, register: Registry = new Registry(), - reservedKeys: Set = new Set(), - redisClient?: RedisClientType, + internalCache: ICacheClient, + sharedCache?: ICacheClient, ) { this.logger = logger; this.register = register; - this.internalCache = new LocalLRUCache(logger.child({ name: 'localLRUCache' }), register, reservedKeys); - this.sharedCache = this.internalCache; - this.isSharedCacheEnabled = !ConfigService.get('TEST') && redisClient !== undefined; + this.internalCache = internalCache; + if (sharedCache) this.sharedCache = sharedCache; this.shouldMultiSet = ConfigService.get('MULTI_SET'); - if (this.isSharedCacheEnabled) { - this.sharedCache = new RedisCache(logger.child({ name: 'redisCache' }), register, redisClient!); - } - /** * Labels: * callingMethod - The method initiating the cache operation @@ -126,7 +111,7 @@ export class CacheService { .labels(callingMethod, CacheService.cacheTypes.REDIS, CacheService.methods.GET_ASYNC) .inc(1); - return await this.sharedCache.get(key, callingMethod); + return await this.sharedCache!.get(key, callingMethod); } catch (error) { const redisError = new RedisCacheError(error); this.logger.error(redisError, 'Error occurred while getting the cache from Redis. Fallback to internal cache.'); @@ -136,6 +121,19 @@ export class CacheService { } } + /** + * Alias for `get`. + * @param key - The cache key. + * @param callingMethod - The name of the calling method. + * @returns A Promise that resolves with the cached value or null if not found. + * @template T - The type of the cached value. + * + * @deprecated + */ + public getAsync(key: string, callingMethod: string): Promise { + return this.get(key, callingMethod); + } + /** * If SharedCacheEnabled will use shared, otherwise will fallback to internal cache. * @param key - The cache key. @@ -143,8 +141,8 @@ export class CacheService { * @returns A Promise that resolves with the cached value or null if not found. * @template T - The type of the cached value. */ - public async getAsync(key: string, callingMethod: string): Promise { - if (this.isSharedCacheEnabled) { + public async get(key: string, callingMethod: string): Promise { + if (this.sharedCache) { return await this.getFromSharedCache(key, callingMethod); } else { return await this.getFromInternalCache(key, callingMethod); @@ -174,7 +172,7 @@ export class CacheService { * @param ttl - Time to live for the cached value in milliseconds (optional). */ public async set(key: string, value: any, callingMethod: string, ttl?: number): Promise { - if (this.isSharedCacheEnabled) { + if (this.sharedCache) { try { this.cacheMethodsCounter.labels(callingMethod, CacheService.cacheTypes.REDIS, CacheService.methods.SET).inc(1); @@ -201,7 +199,7 @@ export class CacheService { * @param ttl - Time to live for the cached value in milliseconds (optional). */ public async multiSet(entries: Record, callingMethod: string, ttl?: number): Promise { - if (this.isSharedCacheEnabled) { + if (this.sharedCache) { const metricsMethod = this.shouldMultiSet ? CacheService.methods.MSET : CacheService.methods.PIPELINE; try { if (this.shouldMultiSet) { @@ -223,6 +221,10 @@ export class CacheService { this.cacheMethodsCounter.labels(callingMethod, CacheService.cacheTypes.LRU, CacheService.methods.SET).inc(1); } + public async pipelineSet(entries: Record, callingMethod: string, ttl?: number): Promise { + throw new Error('pipelineSet not implemented'); + } + /** * Deletes a cached value associated with the given key. * If the shared cache is enabled and an error occurs while deleting from it, just logs the error. @@ -231,7 +233,7 @@ export class CacheService { * @param callingMethod - The name of the method calling the cache. */ public async delete(key: string, callingMethod: string): Promise { - if (this.isSharedCacheEnabled) { + if (this.sharedCache) { try { this.cacheMethodsCounter .labels(callingMethod, CacheService.cacheTypes.REDIS, CacheService.methods.DELETE) @@ -256,7 +258,7 @@ export class CacheService { * Else the internal cache clearing is attempted. */ public async clear(): Promise { - if (this.isSharedCacheEnabled) { + if (this.sharedCache) { try { await this.sharedCache.clear(); return; @@ -278,7 +280,7 @@ export class CacheService { * @returns A Promise that resolves with the new value of the key after incrementing. */ public async incrBy(key: string, amount: number, callingMethod: string): Promise { - if (this.isSharedCacheEnabled && this.sharedCache instanceof RedisCache) { + if (this.sharedCache) { try { this.cacheMethodsCounter .labels(callingMethod, CacheService.cacheTypes.REDIS, CacheService.methods.INCR_BY) @@ -291,16 +293,8 @@ export class CacheService { } } - // Fallback to internal cache - const value = await this.getFromInternalCache(key, callingMethod); - const newValue = value + amount; - const remainingTtl = - this.internalCache instanceof LocalLRUCache - ? await this.internalCache.getRemainingTtl(key, callingMethod) - : undefined; - + const newValue = await this.internalCache.incrBy(key, amount, callingMethod); this.cacheMethodsCounter.labels(callingMethod, CacheService.cacheTypes.LRU, CacheService.methods.SET).inc(1); - await this.internalCache.set(key, newValue, callingMethod, remainingTtl); return newValue; } @@ -313,7 +307,7 @@ export class CacheService { * @returns A Promise that resolves with the new length of the list after pushing. */ public async rPush(key: string, value: any, callingMethod: string): Promise { - if (this.isSharedCacheEnabled && this.sharedCache instanceof RedisCache) { + if (this.sharedCache) { try { this.cacheMethodsCounter .labels(callingMethod, CacheService.cacheTypes.REDIS, CacheService.methods.RPUSH) @@ -327,20 +321,10 @@ export class CacheService { } // Fallback to internal cache - const values = (await this.getFromInternalCache(key, callingMethod)) ?? []; - if (!Array.isArray(values)) { - throw new Error(`Value at key ${key} is not an array`); - } - values.push(value); - const remainingTtl = - this.internalCache instanceof LocalLRUCache - ? await this.internalCache.getRemainingTtl(key, callingMethod) - : undefined; - + const result = await this.internalCache.rPush(key, value, callingMethod); this.cacheMethodsCounter.labels(callingMethod, CacheService.cacheTypes.LRU, CacheService.methods.SET).inc(1); - await this.internalCache.set(key, values, callingMethod, remainingTtl); - return values.length; + return result; } /** @@ -353,7 +337,7 @@ export class CacheService { * @template T - The type of the values in the list. */ public async lRange(key: string, start: number, end: number, callingMethod: string): Promise { - if (this.isSharedCacheEnabled && this.sharedCache instanceof RedisCache) { + if (this.sharedCache) { try { this.cacheMethodsCounter .labels(callingMethod, CacheService.cacheTypes.REDIS, CacheService.methods.LRANGE) @@ -365,16 +349,8 @@ export class CacheService { this.logger.error(redisError, `Error occurred while getting cache in Redis.`); } } - - // Fallback to internal cache - const values = (await this.getFromInternalCache(key, callingMethod)) ?? []; - if (!Array.isArray(values)) { - throw new Error(`Value at key ${key} is not an array`); - } - if (end < 0) { - end = values.length + end; - } - return values.slice(start, end + 1); + this.cacheMethodsCounter.labels(callingMethod, CacheService.cacheTypes.LRU, CacheService.methods.GET).inc(1); + return await this.internalCache.lRange(key, start, end, callingMethod); } /** @@ -384,7 +360,7 @@ export class CacheService { * @returns A Promise that resolves with an array of keys that match the pattern. */ async keys(pattern: string, callingMethod: string): Promise { - if (this.isSharedCacheEnabled && this.sharedCache instanceof RedisCache) { + if (this.sharedCache) { try { return await this.sharedCache.keys(pattern, callingMethod); } catch (error) { @@ -392,7 +368,6 @@ export class CacheService { this.logger.error(redisError, `Error occurred while getting keys from Redis.`); } } - // Fallback to internal cache return this.internalCache.keys(pattern, callingMethod); } diff --git a/packages/relay/tests/lib/clients/redisCache.spec.ts b/packages/relay/tests/lib/clients/redisCache.spec.ts index fc759e3b8a..0d3b9bc048 100644 --- a/packages/relay/tests/lib/clients/redisCache.spec.ts +++ b/packages/relay/tests/lib/clients/redisCache.spec.ts @@ -3,7 +3,6 @@ import chai, { expect } from 'chai'; import chaiAsPromised from 'chai-as-promised'; import { pino } from 'pino'; -import { Registry } from 'prom-client'; import { RedisClientType } from 'redis'; import sinon from 'sinon'; @@ -17,7 +16,6 @@ describe('RedisCache Test Suite', async function () { this.timeout(10000); const logger = pino({ level: 'silent' }); - const registry = new Registry(); const callingMethod = 'RedisCacheTest'; let redisCache: RedisCache; @@ -31,7 +29,7 @@ describe('RedisCache Test Suite', async function () { await redisClientManager.connect(); redisClient = redisClientManager.getClient(); - redisCache = new RedisCache(logger.child({ name: `cache` }), registry, redisClient); + redisCache = new RedisCache(logger.child({ name: `cache` }), redisClient); redisCache['options'].ttl = 100; sinon.spy(redisClient, 'set'); }); diff --git a/packages/relay/tests/lib/config/hbarSpendingPlanConfigService.spec.ts b/packages/relay/tests/lib/config/hbarSpendingPlanConfigService.spec.ts index 1b7ec0803f..a6a4a02d6e 100644 --- a/packages/relay/tests/lib/config/hbarSpendingPlanConfigService.spec.ts +++ b/packages/relay/tests/lib/config/hbarSpendingPlanConfigService.spec.ts @@ -23,6 +23,7 @@ import { IPAddressHbarSpendingPlanNotFoundError, } from '../../../src/lib/db/types/hbarLimiter/errors'; import { SubscriptionTier } from '../../../src/lib/db/types/hbarLimiter/subscriptionTier'; +import { CacheClientFactory } from '../../../src/lib/factories/cacheClientFactory'; import { CacheService } from '../../../src/lib/services/cacheService/cacheService'; import { SpendingPlanConfig } from '../../../src/lib/types/spendingPlanConfig'; import { @@ -169,7 +170,7 @@ describe('HbarSpendingPlanConfigService', function () { } else { redisClient = undefined; } - cacheService = new CacheService( + cacheService = CacheClientFactory.create( logger.child({ name: 'cache-service' }), registry, reservedKeys, diff --git a/packages/relay/tests/lib/eth/eth-helpers.ts b/packages/relay/tests/lib/eth/eth-helpers.ts index d106fdff79..55b26ed3c6 100644 --- a/packages/relay/tests/lib/eth/eth-helpers.ts +++ b/packages/relay/tests/lib/eth/eth-helpers.ts @@ -12,8 +12,8 @@ import { EvmAddressHbarSpendingPlanRepository } from '../../../src/lib/db/reposi import { HbarSpendingPlanRepository } from '../../../src/lib/db/repositories/hbarLimiter/hbarSpendingPlanRepository'; import { IPAddressHbarSpendingPlanRepository } from '../../../src/lib/db/repositories/hbarLimiter/ipAddressHbarSpendingPlanRepository'; import { EthImpl } from '../../../src/lib/eth'; +import { CacheClientFactory } from '../../../src/lib/factories/cacheClientFactory'; import { CommonService } from '../../../src/lib/services'; -import { CacheService } from '../../../src/lib/services/cacheService/cacheService'; import HAPIService from '../../../src/lib/services/hapiService/hapiService'; import { HbarLimitService } from '../../../src/lib/services/hbarLimitService'; @@ -34,7 +34,7 @@ export function generateEthTestEnv(fixedFeeHistory = false) { ConfigServiceTestHelper.dynamicOverride('ETH_FEE_HISTORY_FIXED', fixedFeeHistory); const logger = pino({ level: 'silent' }); const registry = new Registry(); - const cacheService = new CacheService(logger, registry); + const cacheService = CacheClientFactory.create(logger, registry); const mirrorNodeInstance = new MirrorNodeClient( ConfigService.get('MIRROR_NODE_URL'), logger.child({ name: `mirror-node` }), diff --git a/packages/relay/tests/lib/ethGetBlockBy.spec.ts b/packages/relay/tests/lib/ethGetBlockBy.spec.ts index 1deee3c89f..6536efd0dd 100644 --- a/packages/relay/tests/lib/ethGetBlockBy.spec.ts +++ b/packages/relay/tests/lib/ethGetBlockBy.spec.ts @@ -12,6 +12,7 @@ import { nanOrNumberTo0x, nullableNumberTo0x, numberTo0x, toHash32 } from '../.. import { MirrorNodeClient } from '../../src/lib/clients'; import constants from '../../src/lib/constants'; import { EthImpl } from '../../src/lib/eth'; +import { CacheClientFactory } from '../../src/lib/factories/cacheClientFactory'; import { Log, Transaction } from '../../src/lib/model'; import { BlockService, CommonService } from '../../src/lib/services'; import { CacheService } from '../../src/lib/services/cacheService/cacheService'; @@ -108,7 +109,7 @@ describe('eth_getBlockBy', async function () { eval: sinon.stub(), quit: sinon.stub().resolves(true), } as any; - cacheService = new CacheService(logger, registry, new Set(), redisClientMock as any); + cacheService = CacheClientFactory.create(logger, registry, new Set(), redisClientMock as any); // @ts-ignore mirrorNodeInstance = new MirrorNodeClient( diff --git a/packages/relay/tests/lib/hapiService.spec.ts b/packages/relay/tests/lib/hapiService.spec.ts index 4a5e523bc3..14d3321f12 100644 --- a/packages/relay/tests/lib/hapiService.spec.ts +++ b/packages/relay/tests/lib/hapiService.spec.ts @@ -10,6 +10,7 @@ import constants from '../../src/lib/constants'; import { EvmAddressHbarSpendingPlanRepository } from '../../src/lib/db/repositories/hbarLimiter/evmAddressHbarSpendingPlanRepository'; import { HbarSpendingPlanRepository } from '../../src/lib/db/repositories/hbarLimiter/hbarSpendingPlanRepository'; import { IPAddressHbarSpendingPlanRepository } from '../../src/lib/db/repositories/hbarLimiter/ipAddressHbarSpendingPlanRepository'; +import { CacheClientFactory } from '../../src/lib/factories/cacheClientFactory'; import { CacheService } from '../../src/lib/services/cacheService/cacheService'; import HAPIService from '../../src/lib/services/hapiService/hapiService'; import { HbarLimitService } from '../../src/lib/services/hbarLimitService'; @@ -38,7 +39,7 @@ describe('HAPI Service', async function () { this.beforeAll(() => { const duration = constants.HBAR_RATE_LIMIT_DURATION; - cacheService = new CacheService(logger, registry); + cacheService = CacheClientFactory.create(logger, registry); const hbarSpendingPlanRepository = new HbarSpendingPlanRepository(cacheService, logger); const evmAddressHbarSpendingPlanRepository = new EvmAddressHbarSpendingPlanRepository(cacheService, logger); diff --git a/packages/relay/tests/lib/mirrorNodeClient.spec.ts b/packages/relay/tests/lib/mirrorNodeClient.spec.ts index 834e53349b..80c8b80d44 100644 --- a/packages/relay/tests/lib/mirrorNodeClient.spec.ts +++ b/packages/relay/tests/lib/mirrorNodeClient.spec.ts @@ -14,6 +14,7 @@ import { MirrorNodeClientError, predefined } from '../../src'; import { MirrorNodeClient } from '../../src/lib/clients'; import constants from '../../src/lib/constants'; import { SDKClientError } from '../../src/lib/errors/SDKClientError'; +import { CacheClientFactory } from '../../src/lib/factories/cacheClientFactory'; import { CacheService } from '../../src/lib/services/cacheService/cacheService'; import { MirrorNodeTransactionRecord, RequestDetails } from '../../src/lib/types'; import { mockData, random20BytesAddress, withOverriddenEnvsInMochaTest } from '../helpers'; @@ -39,7 +40,7 @@ describe('MirrorNodeClient', async function () { }, timeout: 20 * 1000, }); - cacheService = new CacheService(logger, registry); + cacheService = CacheClientFactory.create(logger, registry); mirrorNodeInstance = new MirrorNodeClient( ConfigService.get('MIRROR_NODE_URL'), logger.child({ name: `mirror-node` }), @@ -51,7 +52,7 @@ describe('MirrorNodeClient', async function () { beforeEach(async () => { mock = new MockAdapter(instance); - await cacheService.clear(requestDetails); + await cacheService.clear(); }); describe('Forwarded Header', () => { diff --git a/packages/relay/tests/lib/openrpc.spec.ts b/packages/relay/tests/lib/openrpc.spec.ts index 0ce03609b2..f6f433cf54 100644 --- a/packages/relay/tests/lib/openrpc.spec.ts +++ b/packages/relay/tests/lib/openrpc.spec.ts @@ -24,6 +24,7 @@ import { EvmAddressHbarSpendingPlanRepository } from '../../src/lib/db/repositor import { HbarSpendingPlanRepository } from '../../src/lib/db/repositories/hbarLimiter/hbarSpendingPlanRepository'; import { IPAddressHbarSpendingPlanRepository } from '../../src/lib/db/repositories/hbarLimiter/ipAddressHbarSpendingPlanRepository'; import { EthImpl } from '../../src/lib/eth'; +import { CacheClientFactory } from '../../src/lib/factories/cacheClientFactory'; import { NetImpl } from '../../src/lib/net'; import { CacheService } from '../../src/lib/services/cacheService/cacheService'; import ClientService from '../../src/lib/services/hapiService/hapiService'; @@ -106,7 +107,7 @@ describe('Open RPC Specification', function () { }); mock = new MockAdapter(instance, { onNoMatch: 'throwException' }); - const cacheService = new CacheService(logger, registry); + const cacheService = CacheClientFactory.create(logger, registry); mirrorNodeInstance = new MirrorNodeClient( ConfigService.get('MIRROR_NODE_URL'), logger.child({ name: `mirror-node` }), diff --git a/packages/relay/tests/lib/precheck.spec.ts b/packages/relay/tests/lib/precheck.spec.ts index 5e1d4ddf00..79acbbe03d 100644 --- a/packages/relay/tests/lib/precheck.spec.ts +++ b/packages/relay/tests/lib/precheck.spec.ts @@ -28,6 +28,7 @@ import { ONE_TINYBAR_IN_WEI_HEX } from './eth/eth-config'; const registry = new Registry(); import sinon from 'sinon'; +import { CacheClientFactory } from '../../src/lib/factories/cacheClientFactory'; import { TransactionPoolService } from '../../src/lib/services/transactionPoolService/transactionPoolService'; import { RequestDetails } from '../../src/lib/types'; @@ -94,7 +95,7 @@ describe('Precheck', async function () { ConfigService.get('MIRROR_NODE_URL')!, logger.child({ name: `mirror-node` }), registry, - new CacheService(logger, registry), + CacheClientFactory.create(logger, registry), instance, ); const transactionPoolService = sinon.createStubInstance(TransactionPoolService); diff --git a/packages/relay/tests/lib/relay.spec.ts b/packages/relay/tests/lib/relay.spec.ts index e4149cf08e..509ae391ce 100644 --- a/packages/relay/tests/lib/relay.spec.ts +++ b/packages/relay/tests/lib/relay.spec.ts @@ -9,7 +9,6 @@ import sinon from 'sinon'; import { Relay } from '../../src'; import { MirrorNodeClient } from '../../src/lib/clients/mirrorNodeClient'; -import { CacheService } from '../../src/lib/services/cacheService/cacheService'; import { overrideEnvsInMochaDescribe, withOverriddenEnvsInMochaTest } from '../helpers'; chai.use(chaiAsPromised); @@ -52,8 +51,6 @@ describe('Relay', () => { let populatePreconfiguredSpendingPlansSpy: sinon.SinonSpy; beforeEach(() => { - // @ts-ignore - CacheService.instances = []; loggerSpy = sinon.spy(logger); populatePreconfiguredSpendingPlansSpy = sinon.spy(Relay.prototype, 'populatePreconfiguredSpendingPlans'); }); diff --git a/packages/relay/tests/lib/repositories/hbarLimiter/evmAddressHbarSpendingPlanRepository.spec.ts b/packages/relay/tests/lib/repositories/hbarLimiter/evmAddressHbarSpendingPlanRepository.spec.ts index 5907cecb3d..e1880f478c 100644 --- a/packages/relay/tests/lib/repositories/hbarLimiter/evmAddressHbarSpendingPlanRepository.spec.ts +++ b/packages/relay/tests/lib/repositories/hbarLimiter/evmAddressHbarSpendingPlanRepository.spec.ts @@ -13,6 +13,7 @@ import { EvmAddressHbarSpendingPlan } from '../../../../src/lib/db/entities/hbar import { EvmAddressHbarSpendingPlanRepository } from '../../../../src/lib/db/repositories/hbarLimiter/evmAddressHbarSpendingPlanRepository'; import { EvmAddressHbarSpendingPlanNotFoundError } from '../../../../src/lib/db/types/hbarLimiter/errors'; import { IEvmAddressHbarSpendingPlan } from '../../../../src/lib/db/types/hbarLimiter/evmAddressHbarSpendingPlan'; +import { CacheClientFactory } from '../../../../src/lib/factories/cacheClientFactory'; import { CacheService } from '../../../../src/lib/services/cacheService/cacheService'; import { overrideEnvsInMochaDescribe, useInMemoryRedisServer } from '../../../helpers'; @@ -44,7 +45,7 @@ describe('@evmAddressHbarSpendingPlanRepository EvmAddressHbarSpendingPlanReposi } else { redisClient = undefined; } - cacheService = new CacheService(logger, registry, new Set(), redisClient); + cacheService = CacheClientFactory.create(logger, registry, new Set(), redisClient); cacheServiceSpy = sinon.spy(cacheService); repository = new EvmAddressHbarSpendingPlanRepository( cacheService, diff --git a/packages/relay/tests/lib/repositories/hbarLimiter/hbarSpendingPlanRepository.spec.ts b/packages/relay/tests/lib/repositories/hbarLimiter/hbarSpendingPlanRepository.spec.ts index 482d930d5a..0301a4a554 100644 --- a/packages/relay/tests/lib/repositories/hbarLimiter/hbarSpendingPlanRepository.spec.ts +++ b/packages/relay/tests/lib/repositories/hbarLimiter/hbarSpendingPlanRepository.spec.ts @@ -16,6 +16,7 @@ import { import { IDetailedHbarSpendingPlan } from '../../../../src/lib/db/types/hbarLimiter/hbarSpendingPlan'; import { IHbarSpendingRecord } from '../../../../src/lib/db/types/hbarLimiter/hbarSpendingRecord'; import { SubscriptionTier } from '../../../../src/lib/db/types/hbarLimiter/subscriptionTier'; +import { CacheClientFactory } from '../../../../src/lib/factories/cacheClientFactory'; import { CacheService } from '../../../../src/lib/services/cacheService/cacheService'; import { overrideEnvsInMochaDescribe, useInMemoryRedisServer } from '../../../helpers'; @@ -47,7 +48,7 @@ describe('HbarSpendingPlanRepository', function () { } else { redisClient = undefined; } - cacheService = new CacheService(logger, registry, new Set(), redisClient); + cacheService = CacheClientFactory.create(logger, registry, new Set(), redisClient); cacheServiceSpy = sinon.spy(cacheService); repository = new HbarSpendingPlanRepository(cacheService, logger.child({ name: `HbarSpendingPlanRepository` })); }); diff --git a/packages/relay/tests/lib/repositories/hbarLimiter/ipAddressHbarSpendingPlanRepository.spec.ts b/packages/relay/tests/lib/repositories/hbarLimiter/ipAddressHbarSpendingPlanRepository.spec.ts index 58e96b7268..aa55714bbb 100644 --- a/packages/relay/tests/lib/repositories/hbarLimiter/ipAddressHbarSpendingPlanRepository.spec.ts +++ b/packages/relay/tests/lib/repositories/hbarLimiter/ipAddressHbarSpendingPlanRepository.spec.ts @@ -12,6 +12,7 @@ import { IPAddressHbarSpendingPlan } from '../../../../src/lib/db/entities/hbarL import { IPAddressHbarSpendingPlanRepository } from '../../../../src/lib/db/repositories/hbarLimiter/ipAddressHbarSpendingPlanRepository'; import { IPAddressHbarSpendingPlanNotFoundError } from '../../../../src/lib/db/types/hbarLimiter/errors'; import { IIPAddressHbarSpendingPlan } from '../../../../src/lib/db/types/hbarLimiter/ipAddressHbarSpendingPlan'; +import { CacheClientFactory } from '../../../../src/lib/factories/cacheClientFactory'; import { CacheService } from '../../../../src/lib/services/cacheService/cacheService'; import { overrideEnvsInMochaDescribe, useInMemoryRedisServer } from '../../../helpers'; @@ -40,7 +41,7 @@ describe('IPAddressHbarSpendingPlanRepository', function () { redisClientManager = new RedisClientManager(logger, 'redis://127.0.0.1:6383', 1000); await redisClientManager.connect(); } - cacheService = new CacheService(logger, registry); + cacheService = CacheClientFactory.create(logger, registry); cacheServiceSpy = sinon.spy(cacheService); repository = new IPAddressHbarSpendingPlanRepository( cacheService, diff --git a/packages/relay/tests/lib/sdkClient.spec.ts b/packages/relay/tests/lib/sdkClient.spec.ts index b82781391c..e627bde6d7 100644 --- a/packages/relay/tests/lib/sdkClient.spec.ts +++ b/packages/relay/tests/lib/sdkClient.spec.ts @@ -39,6 +39,7 @@ import { EvmAddressHbarSpendingPlanRepository } from '../../src/lib/db/repositor import { HbarSpendingPlanRepository } from '../../src/lib/db/repositories/hbarLimiter/hbarSpendingPlanRepository'; import { IPAddressHbarSpendingPlanRepository } from '../../src/lib/db/repositories/hbarLimiter/ipAddressHbarSpendingPlanRepository'; import { SDKClientError } from '../../src/lib/errors/SDKClientError'; +import { CacheClientFactory } from '../../src/lib/factories/cacheClientFactory'; import { CacheService } from '../../src/lib/services/cacheService/cacheService'; import HAPIService from '../../src/lib/services/hapiService/hapiService'; import { HbarLimitService } from '../../src/lib/services/hbarLimitService'; @@ -86,7 +87,7 @@ describe('SdkClient', async function () { const hederaNetwork = ConfigService.get('HEDERA_NETWORK')!; const duration = constants.HBAR_RATE_LIMIT_DURATION; - cacheService = new CacheService(logger, registry); + cacheService = CacheClientFactory.create(logger, registry); const hbarSpendingPlanRepository = new HbarSpendingPlanRepository(cacheService, logger); const evmAddressHbarSpendingPlanRepository = new EvmAddressHbarSpendingPlanRepository(cacheService, logger); const ipAddressHbarSpendingPlanRepository = new IPAddressHbarSpendingPlanRepository(cacheService, logger); diff --git a/packages/relay/tests/lib/services/cacheService/cacheService.spec.ts b/packages/relay/tests/lib/services/cacheService/cacheService.spec.ts index 4f42c59f3d..f87b082940 100644 --- a/packages/relay/tests/lib/services/cacheService/cacheService.spec.ts +++ b/packages/relay/tests/lib/services/cacheService/cacheService.spec.ts @@ -10,6 +10,7 @@ import * as sinon from 'sinon'; import { ICacheClient } from '../../../../src/lib/clients/cache/ICacheClient'; import { LocalLRUCache } from '../../../../src/lib/clients/cache/localLRUCache'; import { RedisClientManager } from '../../../../src/lib/clients/redisClientManager'; +import { CacheClientFactory } from '../../../../src/lib/factories/cacheClientFactory'; import { CacheService } from '../../../../src/lib/services/cacheService/cacheService'; import { overrideEnvsInMochaDescribe, useInMemoryRedisServer } from '../../../helpers'; @@ -28,7 +29,7 @@ describe('CacheService Test Suite', async function () { describe('keys', async function () { let internalCacheSpy: sinon.SinonSpiedInstance; before(async () => { - internalCacheSpy = sinon.spy(cacheService['internalCache']); + internalCacheSpy = sinon.spy(cacheService); }); it('should retrieve all keys', async function () { @@ -135,7 +136,7 @@ describe('CacheService Test Suite', async function () { overrideEnvsInMochaDescribe({ REDIS_ENABLED: false }); this.beforeAll(() => { - cacheService = new CacheService(logger, registry); + cacheService = CacheClientFactory.create(logger, registry); }); this.afterEach(async () => { @@ -237,7 +238,7 @@ describe('CacheService Test Suite', async function () { describe('should not initialize redis cache if shared cache is not enabled', async function () { it('should not initialize redis cache if shared cache is not enabled', async function () { - expect(cacheService['sharedCache']).to.be.an.instanceOf(LocalLRUCache); + expect(cacheService).to.be.an.instanceOf(LocalLRUCache); }); }); }); @@ -254,7 +255,7 @@ describe('CacheService Test Suite', async function () { before(async () => { redisManager = new RedisClientManager(logger, 'redis://127.0.0.1:6381', 1000); - cacheService = new CacheService(logger, registry, new Set(), redisManager.getClient()); + cacheService = CacheClientFactory.create(logger, registry, new Set(), redisManager.getClient()); }); this.beforeEach(async () => { diff --git a/packages/relay/tests/lib/services/eth/filter.spec.ts b/packages/relay/tests/lib/services/eth/filter.spec.ts index 6387f649f4..3c42b8a68c 100644 --- a/packages/relay/tests/lib/services/eth/filter.spec.ts +++ b/packages/relay/tests/lib/services/eth/filter.spec.ts @@ -10,6 +10,7 @@ import { v4 as uuid } from 'uuid'; import { predefined } from '../../../../src'; import { MirrorNodeClient } from '../../../../src/lib/clients'; import constants from '../../../../src/lib/constants'; +import { CacheClientFactory } from '../../../../src/lib/factories/cacheClientFactory'; import { CommonService, FilterService } from '../../../../src/lib/services'; import { CacheService } from '../../../../src/lib/services/cacheService/cacheService'; import { RequestDetails } from '../../../../src/lib/types'; @@ -52,7 +53,7 @@ describe('Filter API Test Suite', async function () { const validateFilterCache = async (filterId: string, expectedFilterType: string, expectedParams = {}) => { const cacheKey = `${constants.CACHE_KEY.FILTERID}_${filterId}`; - const cachedFilter = await cacheService.getAsync(cacheKey, 'validateFilterCache', requestDetails); + const cachedFilter = await cacheService.getAsync(cacheKey, 'validateFilterCache'); expect(cachedFilter).to.exist; expect(cachedFilter.type).to.exist; expect(cachedFilter.type).to.eq(expectedFilterType); @@ -62,7 +63,7 @@ describe('Filter API Test Suite', async function () { }; this.beforeAll(() => { - cacheService = new CacheService(logger, registry); + cacheService = CacheClientFactory.create(logger, registry); mirrorNodeInstance = new MirrorNodeClient( ConfigService.get('MIRROR_NODE_URL'), logger.child({ name: `mirror-node` }), @@ -83,7 +84,7 @@ describe('Filter API Test Suite', async function () { this.beforeEach(async () => { // reset cache and restMock - await cacheService.clear(requestDetails); + await cacheService.clear(); restMock.reset(); }); @@ -334,17 +335,11 @@ describe('Filter API Test Suite', async function () { describe('eth_uninstallFilter', async function () { it('should return true if filter is deleted', async function () { const cacheKey = `${constants.CACHE_KEY.FILTERID}_${existingFilterId}`; - await cacheService.set( - cacheKey, - filterObject, - filterService.ethUninstallFilter, - requestDetails, - constants.FILTER.TTL, - ); + await cacheService.set(cacheKey, filterObject, filterService.ethUninstallFilter, constants.FILTER.TTL); const result = await filterService.uninstallFilter(existingFilterId, requestDetails); - const isDeleted = !(await cacheService.getAsync(cacheKey, filterService.ethUninstallFilter, requestDetails)); + const isDeleted = !(await cacheService.getAsync(cacheKey, filterService.ethUninstallFilter)); expect(result).to.eq(true); expect(isDeleted).to.eq(true); }); @@ -564,13 +559,7 @@ describe('Filter API Test Suite', async function () { .reply(200, JSON.stringify({ blocks: [] })); const cacheKey = `${constants.CACHE_KEY.FILTERID}_${existingFilterId}`; - await cacheService.set( - cacheKey, - blockFilterObject, - filterService.ethGetFilterChanges, - requestDetails, - constants.FILTER.TTL, - ); + await cacheService.set(cacheKey, blockFilterObject, filterService.ethGetFilterChanges, constants.FILTER.TTL); const result = await filterService.getFilterChanges(existingFilterId, requestDetails); expect(result).to.exist; @@ -603,13 +592,7 @@ describe('Filter API Test Suite', async function () { .reply(200, JSON.stringify({ blocks: [] })); const cacheKey = `${constants.CACHE_KEY.FILTERID}_${existingFilterId}`; - await cacheService.set( - cacheKey, - blockFilterObject, - filterService.ethGetFilterChanges, - requestDetails, - constants.FILTER.TTL, - ); + await cacheService.set(cacheKey, blockFilterObject, filterService.ethGetFilterChanges, constants.FILTER.TTL); const resultCurrentBlock = await filterService.getFilterChanges(existingFilterId, requestDetails); expect(resultCurrentBlock).to.not.be.empty; @@ -673,13 +656,7 @@ describe('Filter API Test Suite', async function () { ); const cacheKey = `${constants.CACHE_KEY.FILTERID}_${existingFilterId}`; - await cacheService.set( - cacheKey, - blockFilterObject, - filterService.ethGetFilterChanges, - requestDetails, - constants.FILTER.TTL, - ); + await cacheService.set(cacheKey, blockFilterObject, filterService.ethGetFilterChanges, constants.FILTER.TTL); const blocks = await filterService.getFilterChanges(existingFilterId, requestDetails); expect(blocks).to.be.empty; @@ -697,7 +674,6 @@ describe('Filter API Test Suite', async function () { lastQueried: null, }, filterService.ethGetFilterChanges, - requestDetails, constants.FILTER.TTL, ); diff --git a/packages/relay/tests/lib/services/hbarLimitService/hbarLimitService.spec.ts b/packages/relay/tests/lib/services/hbarLimitService/hbarLimitService.spec.ts index 25356cf364..12c50b08e0 100644 --- a/packages/relay/tests/lib/services/hbarLimitService/hbarLimitService.spec.ts +++ b/packages/relay/tests/lib/services/hbarLimitService/hbarLimitService.spec.ts @@ -6,6 +6,7 @@ import { AccountId, Hbar } from '@hashgraph/sdk'; import chai, { expect } from 'chai'; import chaiAsPromised from 'chai-as-promised'; import { randomBytes, uuidV4 } from 'ethers'; +import Long from 'long'; import pino, { Logger } from 'pino'; import { Counter, Gauge, Registry } from 'prom-client'; import sinon from 'sinon'; @@ -23,6 +24,7 @@ import { } from '../../../../src/lib/db/types/hbarLimiter/errors'; import { IDetailedHbarSpendingPlan } from '../../../../src/lib/db/types/hbarLimiter/hbarSpendingPlan'; import { SubscriptionTier } from '../../../../src/lib/db/types/hbarLimiter/subscriptionTier'; +import { CacheClientFactory } from '../../../../src/lib/factories/cacheClientFactory'; import { CacheService } from '../../../../src/lib/services/cacheService/cacheService'; import { HbarLimitService } from '../../../../src/lib/services/hbarLimitService'; import { RequestDetails } from '../../../../src/lib/types'; @@ -57,7 +59,7 @@ describe('HBAR Rate Limit Service', function () { let loggerSpy: sinon.SinonSpiedInstance; beforeEach(async function () { - cacheService = new CacheService(logger, register); + cacheService = CacheClientFactory.create(logger, register); loggerSpy = sinon.spy(logger); hbarSpendingPlanRepository = new HbarSpendingPlanRepository( cacheService, diff --git a/packages/relay/tests/lib/services/metricService/metricService.spec.ts b/packages/relay/tests/lib/services/metricService/metricService.spec.ts index 7450dd27c7..5250a25e8f 100644 --- a/packages/relay/tests/lib/services/metricService/metricService.spec.ts +++ b/packages/relay/tests/lib/services/metricService/metricService.spec.ts @@ -17,6 +17,7 @@ import constants from '../../../../src/lib/constants'; import { EvmAddressHbarSpendingPlanRepository } from '../../../../src/lib/db/repositories/hbarLimiter/evmAddressHbarSpendingPlanRepository'; import { HbarSpendingPlanRepository } from '../../../../src/lib/db/repositories/hbarLimiter/hbarSpendingPlanRepository'; import { IPAddressHbarSpendingPlanRepository } from '../../../../src/lib/db/repositories/hbarLimiter/ipAddressHbarSpendingPlanRepository'; +import { CacheClientFactory } from '../../../../src/lib/factories/cacheClientFactory'; import { CacheService } from '../../../../src/lib/services/cacheService/cacheService'; import { HbarLimitService } from '../../../../src/lib/services/hbarLimitService'; import MetricService from '../../../../src/lib/services/metricService/metricService'; @@ -135,7 +136,7 @@ describe('Metric Service', function () { ConfigService.get('MIRROR_NODE_URL'), logger.child({ name: `mirror-node` }), registry, - new CacheService(logger, registry), + CacheClientFactory.create(logger, registry), instance, ); }); @@ -147,7 +148,7 @@ describe('Metric Service', function () { eventEmitter = new EventEmitter(); - const cacheService = new CacheService(logger, registry); + const cacheService = CacheClientFactory.create(logger, registry); const hbarSpendingPlanRepository = new HbarSpendingPlanRepository(cacheService, logger); const evmAddressHbarSpendingPlanRepository = new EvmAddressHbarSpendingPlanRepository(cacheService, logger); const ipAddressHbarSpendingPlanRepository = new IPAddressHbarSpendingPlanRepository(cacheService, logger); diff --git a/packages/server/tests/acceptance/cacheService.spec.ts b/packages/server/tests/acceptance/cacheService.spec.ts index 622dc17145..a6642458af 100644 --- a/packages/server/tests/acceptance/cacheService.spec.ts +++ b/packages/server/tests/acceptance/cacheService.spec.ts @@ -9,6 +9,7 @@ import pino, { type Logger } from 'pino'; import { RedisClientType } from 'redis'; import sinon from 'sinon'; +import { CacheClientFactory } from '../../../relay/src/lib/factories/cacheClientFactory'; import { overrideEnvsInMochaDescribe, withOverriddenEnvsInMochaTest } from '../../../relay/tests/helpers'; const DATA_LABEL_PREFIX = 'acceptance-test-'; @@ -28,7 +29,7 @@ describe('@cache-service Acceptance Tests for shared cache', function () { redisManager = new RedisClientManager(logger, 'redis://127.0.0.1:6379', 1000); await redisManager.connect(); redisClient = redisManager.getClient(); - cacheService = new CacheService(logger, undefined, undefined, redisClient); + cacheService = CacheClientFactory.create(logger, undefined, undefined, redisClient); await new Promise((r) => setTimeout(r, 1000)); }); @@ -86,7 +87,7 @@ describe('@cache-service Acceptance Tests for shared cache', function () { it('Falls back to local cache for REDIS_ENABLED !== true', async () => { const dataLabel = `${DATA_LABEL_PREFIX}3`; - const serviceWithDisabledRedis = new CacheService(logger); + const serviceWithDisabledRedis = CacheClientFactory.create(logger); const isRedisEnabled = ConfigService.get('REDIS_ENABLED') && !!ConfigService.get('REDIS_URL'); await new Promise((r) => setTimeout(r, 1000)); expect(isRedisEnabled).to.eq(false); @@ -100,7 +101,7 @@ describe('@cache-service Acceptance Tests for shared cache', function () { it('Cache set by one instance can be accessed by another', async () => { const dataLabel = `${DATA_LABEL_PREFIX}4`; - const otherServiceInstance = new CacheService(logger, undefined, undefined, redisClient); + const otherServiceInstance = CacheClientFactory.create(logger, undefined, undefined, redisClient); await cacheService.set(dataLabel, DATA, CALLING_METHOD); await new Promise((r) => setTimeout(r, 200)); diff --git a/packages/server/tests/acceptance/hbarLimiter.spec.ts b/packages/server/tests/acceptance/hbarLimiter.spec.ts index 6019229bf4..3940cc3c37 100644 --- a/packages/server/tests/acceptance/hbarLimiter.spec.ts +++ b/packages/server/tests/acceptance/hbarLimiter.spec.ts @@ -24,6 +24,7 @@ import { Logger } from 'pino'; import { Registry } from 'prom-client'; import { RedisClientType } from 'redis'; +import { CacheClientFactory } from '../../../relay/src/lib/factories/cacheClientFactory'; import MetricsClient from '../clients/metricsClient'; import MirrorClient from '../clients/mirrorClient'; import RelayClient from '../clients/relayClient'; @@ -95,7 +96,12 @@ describe('@hbarlimiter HBAR Limiter Acceptance Tests', function () { const register = new Registry(); const reservedKeys = HbarSpendingPlanConfigService.getPreconfiguredSpendingPlanKeys(logger); - cacheService = new CacheService(logger.child({ name: 'cache-service' }), register, reservedKeys, redisClient); + cacheService = CacheClientFactory.create( + logger.child({ name: 'cache-service' }), + register, + reservedKeys, + redisClient, + ); evmAddressSpendingPlanRepository = new EvmAddressHbarSpendingPlanRepository(cacheService, logger); ipSpendingPlanRepository = new IPAddressHbarSpendingPlanRepository(cacheService, logger);