@@ -12,6 +12,15 @@ import { IRedisCacheClient } from './IRedisCacheClient';
1212 * A class that provides caching functionality using Redis.
1313 */
1414export class RedisCache implements IRedisCacheClient {
15+ /**
16+ * Prefix used to namespace all keys managed by this cache.
17+ *
18+ * @remarks
19+ * Using a prefix allows efficient scanning and cleanup of related keys
20+ * without interfering with keys from other services (e.g., pending:, hbar-limit:).
21+ */
22+ private static readonly CACHE_KEY_PREFIX = 'cache:' ;
23+
1524 /**
1625 * Configurable options used when initializing the cache.
1726 *
@@ -52,6 +61,17 @@ export class RedisCache implements IRedisCacheClient {
5261 this . client = client ;
5362 }
5463
64+ /**
65+ * Adds the cache prefix to a key.
66+ *
67+ * @param key - The key to prefix.
68+ * @returns The prefixed key.
69+ * @private
70+ */
71+ private prefixKey ( key : string ) : string {
72+ return `${ RedisCache . CACHE_KEY_PREFIX } ${ key } ` ;
73+ }
74+
5575 /**
5676 * Retrieves a value from the cache.
5777 *
@@ -60,7 +80,8 @@ export class RedisCache implements IRedisCacheClient {
6080 * @returns The cached value or null if not found.
6181 */
6282 async get ( key : string , callingMethod : string ) : Promise < any > {
63- const result = await this . client . get ( key ) ;
83+ const prefixedKey = this . prefixKey ( key ) ;
84+ const result = await this . client . get ( prefixedKey ) ;
6485 if ( result ) {
6586 if ( this . logger . isLevelEnabled ( 'trace' ) ) {
6687 const censoredKey = key . replace ( Utils . IP_ADDRESS_REGEX , '<REDACTED>' ) ;
@@ -83,12 +104,13 @@ export class RedisCache implements IRedisCacheClient {
83104 * @returns A Promise that resolves when the value is cached.
84105 */
85106 async set ( key : string , value : any , callingMethod : string , ttl ?: number ) : Promise < void > {
107+ const prefixedKey = this . prefixKey ( key ) ;
86108 const serializedValue = JSON . stringify ( value ) ;
87109 const resolvedTtl = ttl ?? this . options . ttl ; // in milliseconds
88110 if ( resolvedTtl > 0 ) {
89- await this . client . set ( key , serializedValue , { PX : resolvedTtl } ) ;
111+ await this . client . set ( prefixedKey , serializedValue , { PX : resolvedTtl } ) ;
90112 } else {
91- await this . client . set ( key , serializedValue ) ;
113+ await this . client . set ( prefixedKey , serializedValue ) ;
92114 }
93115
94116 const censoredKey = key . replace ( Utils . IP_ADDRESS_REGEX , '<REDACTED>' ) ;
@@ -110,10 +132,11 @@ export class RedisCache implements IRedisCacheClient {
110132 * @returns A Promise that resolves when the values are cached.
111133 */
112134 async multiSet ( keyValuePairs : Record < string , any > , callingMethod : string ) : Promise < void > {
113- // Serialize values
135+ // Serialize values and add prefix
114136 const serializedKeyValuePairs : Record < string , string > = { } ;
115137 for ( const [ key , value ] of Object . entries ( keyValuePairs ) ) {
116- serializedKeyValuePairs [ key ] = JSON . stringify ( value ) ;
138+ const prefixedKey = this . prefixKey ( key ) ;
139+ serializedKeyValuePairs [ prefixedKey ] = JSON . stringify ( value ) ;
117140 }
118141
119142 // Perform mSet operation
@@ -140,8 +163,9 @@ export class RedisCache implements IRedisCacheClient {
140163 const pipeline = this . client . multi ( ) ;
141164
142165 for ( const [ key , value ] of Object . entries ( keyValuePairs ) ) {
166+ const prefixedKey = this . prefixKey ( key ) ;
143167 const serializedValue = JSON . stringify ( value ) ;
144- pipeline . set ( key , serializedValue , { PX : resolvedTtl } ) ;
168+ pipeline . set ( prefixedKey , serializedValue , { PX : resolvedTtl } ) ;
145169 }
146170
147171 // Execute pipeline operation
@@ -162,7 +186,8 @@ export class RedisCache implements IRedisCacheClient {
162186 * @returns A Promise that resolves when the value is deleted from the cache.
163187 */
164188 async delete ( key : string , callingMethod : string ) : Promise < void > {
165- await this . client . del ( key ) ;
189+ const prefixedKey = this . prefixKey ( key ) ;
190+ await this . client . del ( prefixedKey ) ;
166191 if ( this . logger . isLevelEnabled ( 'trace' ) ) {
167192 this . logger . trace ( `delete cache for ${ key } on ${ callingMethod } call` ) ;
168193 }
@@ -178,7 +203,8 @@ export class RedisCache implements IRedisCacheClient {
178203 * @returns The value of the key after incrementing
179204 */
180205 async incrBy ( key : string , amount : number , callingMethod : string ) : Promise < number > {
181- const result = await this . client . incrBy ( key , amount ) ;
206+ const prefixedKey = this . prefixKey ( key ) ;
207+ const result = await this . client . incrBy ( prefixedKey , amount ) ;
182208 if ( this . logger . isLevelEnabled ( 'trace' ) ) {
183209 this . logger . trace ( `incrementing ${ key } by ${ amount } on ${ callingMethod } call` ) ;
184210 }
@@ -195,7 +221,8 @@ export class RedisCache implements IRedisCacheClient {
195221 * @returns The list of elements in the range
196222 */
197223 async lRange ( key : string , start : number , end : number , callingMethod : string ) : Promise < any [ ] > {
198- const result = await this . client . lRange ( key , start , end ) ;
224+ const prefixedKey = this . prefixKey ( key ) ;
225+ const result = await this . client . lRange ( prefixedKey , start , end ) ;
199226 if ( this . logger . isLevelEnabled ( 'trace' ) ) {
200227 this . logger . trace ( `retrieving range [${ start } :${ end } ] from ${ key } on ${ callingMethod } call` ) ;
201228 }
@@ -211,8 +238,9 @@ export class RedisCache implements IRedisCacheClient {
211238 * @returns The length of the list after pushing
212239 */
213240 async rPush ( key : string , value : any , callingMethod : string ) : Promise < number > {
241+ const prefixedKey = this . prefixKey ( key ) ;
214242 const serializedValue = JSON . stringify ( value ) ;
215- const result = await this . client . rPush ( key , serializedValue ) ;
243+ const result = await this . client . rPush ( prefixedKey , serializedValue ) ;
216244 if ( this . logger . isLevelEnabled ( 'trace' ) ) {
217245 this . logger . trace ( `pushing ${ serializedValue } to ${ key } on ${ callingMethod } call` ) ;
218246 }
@@ -223,27 +251,26 @@ export class RedisCache implements IRedisCacheClient {
223251 * Retrieves all keys matching a pattern.
224252 * @param pattern The pattern to match
225253 * @param callingMethod The name of the calling method
226- * @returns The list of keys matching the pattern
254+ * @returns The list of keys matching the pattern (without the cache prefix)
227255 */
228256 async keys ( pattern : string , callingMethod : string ) : Promise < string [ ] > {
229- const result = await this . client . keys ( pattern ) ;
257+ const prefixedPattern = this . prefixKey ( pattern ) ;
258+ const result = await this . client . keys ( prefixedPattern ) ;
230259 if ( this . logger . isLevelEnabled ( 'trace' ) ) {
231260 this . logger . trace ( `retrieving keys matching ${ pattern } on ${ callingMethod } call` ) ;
232261 }
233- return result ;
262+ // Remove the prefix from the returned keys
263+ return result . map ( ( key ) => key . substring ( RedisCache . CACHE_KEY_PREFIX . length ) ) ;
234264 }
235265
236266 /**
237- * Clears the entire cache leaving out the transaction pool .
267+ * Clears only the cache keys (those with cache: prefix) .
238268 * Uses pipelining for efficient bulk deletion with UNLINK (non-blocking).
239269 *
240270 * @returns {Promise<void> } A Promise that resolves when the cache is cleared.
241271 */
242272 async clear ( ) : Promise < void > {
243- const allKeys = await this . client . keys ( '*' ) ;
244-
245- // Filter out keys that start with "pending:"
246- const keysToDelete = allKeys . filter ( ( key ) => ! key . startsWith ( 'pending:' ) ) ;
273+ const keysToDelete = await this . client . keys ( `${ RedisCache . CACHE_KEY_PREFIX } *` ) ;
247274
248275 if ( keysToDelete . length > 0 ) {
249276 // Use pipeline for efficient bulk deletion
@@ -256,7 +283,7 @@ export class RedisCache implements IRedisCacheClient {
256283 await pipeline . exec ( ) ;
257284
258285 if ( this . logger . isLevelEnabled ( 'trace' ) ) {
259- this . logger . trace ( ' Cleared cache' ) ;
286+ this . logger . trace ( ` Cleared ${ keysToDelete . length } cache keys` ) ;
260287 }
261288 }
262289 }
0 commit comments