@common-stack/store-redis 8.3.1-alpha.5 → 8.3.1-alpha.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -62,7 +62,9 @@ export declare class RedisCacheManager implements IRedisCacheManager {
|
|
|
62
62
|
/**
|
|
63
63
|
* Generate cache key for a GraphQL query
|
|
64
64
|
*
|
|
65
|
-
* Format:
|
|
65
|
+
* Format:
|
|
66
|
+
* - With userId (PRIVATE): APP_NAME:tenantId:userId:queryName:queryHash:variablesHash
|
|
67
|
+
* - Without userId (PUBLIC): APP_NAME:tenantId:queryName:queryHash:variablesHash
|
|
66
68
|
*/
|
|
67
69
|
private getCacheKey;
|
|
68
70
|
/**
|
|
@@ -35,22 +35,30 @@ let RedisCacheManager = RedisCacheManager_1 = class RedisCacheManager {
|
|
|
35
35
|
* @param shouldRemoveAll - If true, removes all related cache keys
|
|
36
36
|
*/
|
|
37
37
|
async del(query, variables, ctx, shouldRemoveAll = false) {
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
// Clear both PUBLIC and PRIVATE versions of the cache
|
|
39
|
+
const privateKey = this.getCacheKey(query, variables ?? {}, ctx, { maxAge: 1, scope: 'PRIVATE' });
|
|
40
|
+
const publicKey = this.getCacheKey(query, variables ?? {}, ctx, { maxAge: 1, scope: 'PUBLIC' });
|
|
41
|
+
// If variables provided, delete exact match (both versions)
|
|
40
42
|
if (variables && Object.keys(variables).length > 0) {
|
|
41
|
-
this.log('debug', `Deleting ${
|
|
42
|
-
await this.redisClient.del(
|
|
43
|
+
this.log('debug', `Deleting ${privateKey} and ${publicKey} from redis`);
|
|
44
|
+
await this.redisClient.del(privateKey, publicKey);
|
|
43
45
|
return;
|
|
44
46
|
}
|
|
45
|
-
// Build wildcard
|
|
46
|
-
const
|
|
47
|
+
// Build wildcard patterns for both PUBLIC and PRIVATE
|
|
48
|
+
const privatePattern = shouldRemoveAll
|
|
47
49
|
? this.getWildCardQueryKey(query, ctx)
|
|
48
|
-
: `${
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
: `${privateKey.substring(0, privateKey.lastIndexOf(':'))}:*`;
|
|
51
|
+
const publicPattern = shouldRemoveAll
|
|
52
|
+
? this.getWildCardQueryKey(query, ctx)
|
|
53
|
+
: `${publicKey.substring(0, publicKey.lastIndexOf(':'))}:*`;
|
|
54
|
+
// Get keys matching both patterns
|
|
55
|
+
const privateCacheKeys = await this.redisClient.keys(privatePattern);
|
|
56
|
+
const publicCacheKeys = await this.redisClient.keys(publicPattern);
|
|
57
|
+
const allKeys = [...new Set([...privateCacheKeys, ...publicCacheKeys])]; // Deduplicate
|
|
58
|
+
this.log('debug', `Found ${allKeys.length} keys against patterns ${privatePattern} and ${publicPattern}`);
|
|
59
|
+
if (allKeys.length) {
|
|
60
|
+
this.log('debug', `Deleting ${allKeys.length} keys from redis`);
|
|
61
|
+
await this.redisClient.del(...allKeys);
|
|
54
62
|
}
|
|
55
63
|
}
|
|
56
64
|
/**
|
|
@@ -62,8 +70,14 @@ let RedisCacheManager = RedisCacheManager_1 = class RedisCacheManager {
|
|
|
62
70
|
* @returns Cached data or null if cache miss
|
|
63
71
|
*/
|
|
64
72
|
async get(query, variables, ctx) {
|
|
65
|
-
|
|
66
|
-
|
|
73
|
+
// Try PRIVATE key first (with userId)
|
|
74
|
+
let cacheKey = this.getCacheKey(query, variables, ctx, { maxAge: 1, scope: 'PRIVATE' });
|
|
75
|
+
let cacheResponse = await this.redisClient.get(cacheKey);
|
|
76
|
+
// If not found, try PUBLIC key (without userId)
|
|
77
|
+
if (!cacheResponse) {
|
|
78
|
+
cacheKey = this.getCacheKey(query, variables, ctx, { maxAge: 1, scope: 'PUBLIC' });
|
|
79
|
+
cacheResponse = await this.redisClient.get(cacheKey);
|
|
80
|
+
}
|
|
67
81
|
if (cacheResponse) {
|
|
68
82
|
try {
|
|
69
83
|
const { data } = JSON.parse(JSON.parse(cacheResponse)?.value) ?? {};
|
|
@@ -89,7 +103,7 @@ let RedisCacheManager = RedisCacheManager_1 = class RedisCacheManager {
|
|
|
89
103
|
* @param cachePolicy - Cache policy (TTL, scope)
|
|
90
104
|
*/
|
|
91
105
|
async set(query, variables, data, ctx, cachePolicy = { maxAge: 86400, scope: 'PUBLIC' }) {
|
|
92
|
-
const cacheKey = this.getCacheKey(query, variables, ctx);
|
|
106
|
+
const cacheKey = this.getCacheKey(query, variables, ctx, cachePolicy);
|
|
93
107
|
const cacheTime = Date.now();
|
|
94
108
|
// Ensure maxAge is not negative or zero
|
|
95
109
|
const maxAge = Math.max(1, cachePolicy.maxAge);
|
|
@@ -129,16 +143,11 @@ let RedisCacheManager = RedisCacheManager_1 = class RedisCacheManager {
|
|
|
129
143
|
/**
|
|
130
144
|
* Generate cache key for a GraphQL query
|
|
131
145
|
*
|
|
132
|
-
* Format:
|
|
146
|
+
* Format:
|
|
147
|
+
* - With userId (PRIVATE): APP_NAME:tenantId:userId:queryName:queryHash:variablesHash
|
|
148
|
+
* - Without userId (PUBLIC): APP_NAME:tenantId:queryName:queryHash:variablesHash
|
|
133
149
|
*/
|
|
134
|
-
getCacheKey(query, variables, ctx) {
|
|
135
|
-
// Generate the legacy key WITHOUT tenantId/userId since we'll add them via manual construction
|
|
136
|
-
const legacyKey = generateQueryCacheKey({
|
|
137
|
-
query,
|
|
138
|
-
variables,
|
|
139
|
-
logger: this.logger,
|
|
140
|
-
});
|
|
141
|
-
// Build key without namespace - format: APP_NAME:tenantId:userId:legacyKey
|
|
150
|
+
getCacheKey(query, variables, ctx, cachePolicy) {
|
|
142
151
|
const appName = this.getAppName();
|
|
143
152
|
// Validate tenantId - if it looks like a hash (all hex, 24+ chars), use 'default'
|
|
144
153
|
let tenantId = ctx?.tenantId || 'default';
|
|
@@ -146,12 +155,20 @@ let RedisCacheManager = RedisCacheManager_1 = class RedisCacheManager {
|
|
|
146
155
|
this.log('warn', `TenantId appears to be a hash (${tenantId.substring(0, 16)}...), using "default" instead`);
|
|
147
156
|
tenantId = 'default';
|
|
148
157
|
}
|
|
149
|
-
|
|
150
|
-
//
|
|
151
|
-
const
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
158
|
+
// For PUBLIC scope, omit userId to share cache across all users
|
|
159
|
+
// For PRIVATE scope or when not specified, include userId (or 'anonymous')
|
|
160
|
+
const isPublicScope = cachePolicy?.scope === 'PUBLIC';
|
|
161
|
+
const userId = isPublicScope ? undefined : ctx?.userId || 'anonymous';
|
|
162
|
+
// Use generateQueryCacheKey with all parameters to avoid duplication
|
|
163
|
+
// This will properly sanitize userId (auth0|123 -> auth0-123) and build the complete key
|
|
164
|
+
return generateQueryCacheKey({
|
|
165
|
+
query,
|
|
166
|
+
variables,
|
|
167
|
+
appName,
|
|
168
|
+
tenantId,
|
|
169
|
+
userId,
|
|
170
|
+
logger: this.logger,
|
|
171
|
+
});
|
|
155
172
|
}
|
|
156
173
|
/**
|
|
157
174
|
* Clear all cache entries for a tenant
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RedisCacheManager.js","sources":["../../src/services/RedisCacheManager.ts"],"sourcesContent":["/**\n * @file RedisCacheManager.ts\n * @description Redis-based cache manager for GraphQL query caching\n *\n * This implementation provides sophisticated caching for GraphQL operations with:\n * - Automatic query hashing for cache keys\n * - Multi-tenant and user isolation\n * - Wildcard-based cache invalidation\n * - TTL-based expiration\n * - Automatic key sanitization (handles Auth0 userIds with pipes)\n *\n * Migrated from @adminide-stack/platform-server to be shared across applications\n */\n\nimport { generateQueryCacheKey, sanitizeRedisKeyComponent, isHashLikeTenantId } from '../core/keyBuilder';\nimport type { Redis } from 'ioredis';\nimport { print } from 'graphql';\nimport type { DocumentNode } from 'graphql';\nimport { injectable, inject } from 'inversify';\nimport { type ICacheContext, type ICachePolicy, type IRedisCacheManager, SERVER_TYPES } from 'common/server';\nimport { CommonType } from '@common-stack/core';\n\n/**\n * Redis Cache Manager implementation\n *\n * Provides GraphQL query caching with automatic key generation and invalidation\n */\n@injectable()\nexport class RedisCacheManager implements IRedisCacheManager {\n protected logger?: any;\n\n constructor(\n @inject(SERVER_TYPES.RedisClient)\n protected readonly redisClient: Redis,\n @inject(CommonType.LOGGER)\n logger?: any,\n ) {\n if (logger) {\n this.logger = logger.child ? logger.child({ className: RedisCacheManager.name }) : logger;\n }\n }\n\n /**\n * Delete cached data for a GraphQL query\n *\n * @param query - GraphQL query to invalidate\n * @param variables - Optional variables (if omitted, clears all variants)\n * @param ctx - Cache context for tenant/user isolation\n * @param shouldRemoveAll - If true, removes all related cache keys\n */\n async del(\n query: string | DocumentNode,\n variables?: Record<string, unknown>,\n ctx?: ICacheContext,\n shouldRemoveAll = false,\n ): Promise<void> {\n const cacheKey = this.getCacheKey(query, variables ?? {}, ctx);\n\n // If variables provided, delete exact match\n if (variables && Object.keys(variables).length > 0) {\n this.log('debug', `Deleting ${cacheKey} from redis`);\n await this.redisClient.del(cacheKey);\n return;\n }\n\n // Build wildcard pattern\n const keysWithWildCard = shouldRemoveAll\n ? this.getWildCardQueryKey(query, ctx)\n : `${cacheKey.substring(0, cacheKey.lastIndexOf(':'))}:*`;\n\n const cacheKeys = await this.redisClient.keys(keysWithWildCard);\n this.log('debug', `Found ${cacheKeys.length} keys against pattern ${keysWithWildCard}`);\n\n if (cacheKeys.length) {\n this.log('debug', `Deleting ${cacheKeys.length} keys from redis`);\n await this.redisClient.del(...cacheKeys);\n }\n }\n\n /**\n * Get cached data for a GraphQL query\n *\n * @param query - GraphQL query\n * @param variables - Query variables\n * @param ctx - Cache context\n * @returns Cached data or null if cache miss\n */\n async get<T>(\n query: string | DocumentNode,\n variables: Record<string, unknown>,\n ctx: ICacheContext,\n ): Promise<T | null> {\n const cacheKey = this.getCacheKey(query, variables, ctx);\n const cacheResponse = await this.redisClient.get(cacheKey);\n\n if (cacheResponse) {\n try {\n const { data } = JSON.parse(JSON.parse(cacheResponse)?.value) ?? {};\n const queryName = this.getQueryName(query);\n this.log('debug', `Found cache for ${cacheKey}`);\n return data?.[queryName] ?? null;\n } catch (error) {\n this.log('warn', `Failed to parse cache data for ${cacheKey}:`, error);\n return null;\n }\n }\n\n this.log('debug', `No cache found for key ${cacheKey}`);\n return null;\n }\n\n /**\n * Set cached data for a GraphQL query\n *\n * @param query - GraphQL query\n * @param variables - Query variables\n * @param data - Data to cache\n * @param ctx - Cache context\n * @param cachePolicy - Cache policy (TTL, scope)\n */\n async set<T>(\n query: string | DocumentNode,\n variables: Record<string, unknown>,\n data: T,\n ctx: ICacheContext,\n cachePolicy: ICachePolicy = { maxAge: 86400, scope: 'PUBLIC' },\n ): Promise<void> {\n const cacheKey = this.getCacheKey(query, variables, ctx);\n const cacheTime = Date.now();\n\n // Ensure maxAge is not negative or zero\n const maxAge = Math.max(1, cachePolicy.maxAge);\n\n if (cachePolicy.maxAge <= 0) {\n this.log(\n 'warn',\n `Invalid maxAge (${cachePolicy.maxAge}) for cache key ${cacheKey}, using minimum value of 1 second`,\n );\n }\n\n this.log('debug', `Set cache for key ${cacheKey} with maxAge ${maxAge}`);\n\n await this.redisClient.set(\n cacheKey,\n JSON.stringify({\n value: JSON.stringify({\n data: { [this.getQueryName(query)]: data },\n cachePolicy: { ...cachePolicy, maxAge },\n cacheTime,\n }),\n expires: cacheTime + maxAge * 1000,\n }).trim(),\n 'EX',\n maxAge,\n );\n }\n\n /**\n * Extract query name from GraphQL query\n */\n private getQueryName(query: string | DocumentNode): string {\n const queryStr = typeof query === 'string' ? query : print(query);\n const [, queryName] = queryStr?.match(/{\\s*(\\w+)/) ?? [];\n return queryName;\n }\n\n /**\n * Build wildcard pattern for query invalidation\n */\n private getWildCardQueryKey(query: string | DocumentNode, ctx?: ICacheContext): string {\n const queryStr = typeof query === 'string' ? query : print(query);\n const [, queryName] = queryStr?.match(/{\\s*(\\w+)/) ?? [];\n const { tenantId } = ctx || {};\n\n // Build pattern without namespace - just APP_NAME:tenantId:segments\n const appName = this.getAppName();\n const sanitizedTenantId = tenantId || 'default';\n return `${appName}:${sanitizedTenantId}:*:${queryName || '*'}:*`;\n }\n\n /**\n * Generate cache key for a GraphQL query\n *\n * Format: APP_NAME:tenantId:userId:queryName:queryHash:variablesHash\n */\n private getCacheKey(query: string | DocumentNode, variables: Record<string, unknown>, ctx?: ICacheContext): string {\n // Generate the legacy key WITHOUT tenantId/userId since we'll add them via manual construction\n const legacyKey = generateQueryCacheKey({\n query,\n variables,\n logger: this.logger,\n });\n\n // Build key without namespace - format: APP_NAME:tenantId:userId:legacyKey\n const appName = this.getAppName();\n\n // Validate tenantId - if it looks like a hash (all hex, 24+ chars), use 'default'\n let tenantId = ctx?.tenantId || 'default';\n if (isHashLikeTenantId(tenantId)) {\n this.log(\n 'warn',\n `TenantId appears to be a hash (${tenantId.substring(0, 16)}...), using \"default\" instead`,\n );\n tenantId = 'default';\n }\n\n const userId = ctx?.userId || 'anonymous';\n\n // Sanitize components (handles Auth0 userIds like \"auth0|123\")\n const sanitizedAppName = sanitizeRedisKeyComponent(appName);\n const sanitizedTenantId = sanitizeRedisKeyComponent(tenantId);\n const sanitizedUserId = sanitizeRedisKeyComponent(userId);\n\n return `${sanitizedAppName}:${sanitizedTenantId}:${sanitizedUserId}:${legacyKey}`;\n }\n\n /**\n * Clear all cache entries for a tenant\n */\n async clearTenant(tenantId: string): Promise<number> {\n const appName = this.getAppName();\n const sanitizedTenantId = sanitizeRedisKeyComponent(tenantId);\n const pattern = `${appName}:${sanitizedTenantId}:*`;\n\n return await this.clearPattern(pattern);\n }\n\n /**\n * Clear all cache entries for a user\n */\n async clearUser(userId: string, tenantId?: string): Promise<number> {\n const appName = this.getAppName();\n const sanitizedUserId = sanitizeRedisKeyComponent(userId);\n const sanitizedTenantId = tenantId ? sanitizeRedisKeyComponent(tenantId) : '*';\n const pattern = `${appName}:${sanitizedTenantId}:${sanitizedUserId}:*`;\n\n return await this.clearPattern(pattern);\n }\n\n /**\n * Clear all cache entries matching a pattern\n */\n async clearPattern(pattern: string): Promise<number> {\n this.log('debug', `Clearing cache entries matching pattern: ${pattern}`);\n\n const keys = await this.redisClient.keys(pattern);\n\n if (keys.length === 0) {\n this.log('debug', `No keys found matching pattern: ${pattern}`);\n return 0;\n }\n\n this.log('debug', `Deleting ${keys.length} keys matching pattern: ${pattern}`);\n await this.redisClient.del(...keys);\n\n return keys.length;\n }\n\n /**\n * Get cache statistics\n */\n async getStats(tenantId?: string): Promise<{\n totalKeys: number;\n memoryUsage: number;\n hitRate?: number;\n }> {\n const appName = this.getAppName();\n const pattern = tenantId ? `${appName}:${sanitizeRedisKeyComponent(tenantId)}:*` : `${appName}:*`;\n\n const keys = await this.redisClient.keys(pattern);\n const totalKeys = keys.length;\n\n // Get memory usage for the Redis instance\n let memoryUsage = 0;\n try {\n const info = await this.redisClient.info('memory');\n const match = info.match(/used_memory:(\\d+)/);\n if (match) {\n memoryUsage = parseInt(match[1], 10);\n }\n } catch (error) {\n this.log('warn', 'Failed to get memory info from Redis:', error);\n }\n\n return {\n totalKeys,\n memoryUsage,\n hitRate: undefined, // Hit rate tracking would require additional instrumentation\n };\n }\n\n /**\n * Get application name for key prefix\n * Override this method to provide custom app name\n */\n protected getAppName(): string {\n return process.env.APP_NAME || 'COMMON_STACK';\n }\n\n /**\n * Log helper\n */\n private log(level: string, message: string, ...args: any[]): void {\n if (this.logger && typeof this.logger[level] === 'function') {\n this.logger[level](message, ...args);\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RedisCacheManager.js","sources":["../../src/services/RedisCacheManager.ts"],"sourcesContent":["/**\n * @file RedisCacheManager.ts\n * @description Redis-based cache manager for GraphQL query caching\n *\n * This implementation provides sophisticated caching for GraphQL operations with:\n * - Automatic query hashing for cache keys\n * - Multi-tenant and user isolation\n * - Wildcard-based cache invalidation\n * - TTL-based expiration\n * - Automatic key sanitization (handles Auth0 userIds with pipes)\n *\n * Migrated from @adminide-stack/platform-server to be shared across applications\n */\n\nimport { generateQueryCacheKey, sanitizeRedisKeyComponent, isHashLikeTenantId } from '../core/keyBuilder';\nimport type { Redis } from 'ioredis';\nimport { print } from 'graphql';\nimport type { DocumentNode } from 'graphql';\nimport { injectable, inject } from 'inversify';\nimport { type ICacheContext, type ICachePolicy, type IRedisCacheManager, SERVER_TYPES } from 'common/server';\nimport { CommonType } from '@common-stack/core';\n\n/**\n * Redis Cache Manager implementation\n *\n * Provides GraphQL query caching with automatic key generation and invalidation\n */\n@injectable()\nexport class RedisCacheManager implements IRedisCacheManager {\n protected logger?: any;\n\n constructor(\n @inject(SERVER_TYPES.RedisClient)\n protected readonly redisClient: Redis,\n @inject(CommonType.LOGGER)\n logger?: any,\n ) {\n if (logger) {\n this.logger = logger.child ? logger.child({ className: RedisCacheManager.name }) : logger;\n }\n }\n\n /**\n * Delete cached data for a GraphQL query\n *\n * @param query - GraphQL query to invalidate\n * @param variables - Optional variables (if omitted, clears all variants)\n * @param ctx - Cache context for tenant/user isolation\n * @param shouldRemoveAll - If true, removes all related cache keys\n */\n async del(\n query: string | DocumentNode,\n variables?: Record<string, unknown>,\n ctx?: ICacheContext,\n shouldRemoveAll = false,\n ): Promise<void> {\n // Clear both PUBLIC and PRIVATE versions of the cache\n const privateKey = this.getCacheKey(query, variables ?? {}, ctx, { maxAge: 1, scope: 'PRIVATE' });\n const publicKey = this.getCacheKey(query, variables ?? {}, ctx, { maxAge: 1, scope: 'PUBLIC' });\n\n // If variables provided, delete exact match (both versions)\n if (variables && Object.keys(variables).length > 0) {\n this.log('debug', `Deleting ${privateKey} and ${publicKey} from redis`);\n await this.redisClient.del(privateKey, publicKey);\n return;\n }\n\n // Build wildcard patterns for both PUBLIC and PRIVATE\n const privatePattern = shouldRemoveAll\n ? this.getWildCardQueryKey(query, ctx)\n : `${privateKey.substring(0, privateKey.lastIndexOf(':'))}:*`;\n\n const publicPattern = shouldRemoveAll\n ? this.getWildCardQueryKey(query, ctx)\n : `${publicKey.substring(0, publicKey.lastIndexOf(':'))}:*`;\n\n // Get keys matching both patterns\n const privateCacheKeys = await this.redisClient.keys(privatePattern);\n const publicCacheKeys = await this.redisClient.keys(publicPattern);\n const allKeys = [...new Set([...privateCacheKeys, ...publicCacheKeys])]; // Deduplicate\n\n this.log('debug', `Found ${allKeys.length} keys against patterns ${privatePattern} and ${publicPattern}`);\n\n if (allKeys.length) {\n this.log('debug', `Deleting ${allKeys.length} keys from redis`);\n await this.redisClient.del(...allKeys);\n }\n }\n\n /**\n * Get cached data for a GraphQL query\n *\n * @param query - GraphQL query\n * @param variables - Query variables\n * @param ctx - Cache context\n * @returns Cached data or null if cache miss\n */\n async get<T>(\n query: string | DocumentNode,\n variables: Record<string, unknown>,\n ctx: ICacheContext,\n ): Promise<T | null> {\n // Try PRIVATE key first (with userId)\n let cacheKey = this.getCacheKey(query, variables, ctx, { maxAge: 1, scope: 'PRIVATE' });\n let cacheResponse = await this.redisClient.get(cacheKey);\n\n // If not found, try PUBLIC key (without userId)\n if (!cacheResponse) {\n cacheKey = this.getCacheKey(query, variables, ctx, { maxAge: 1, scope: 'PUBLIC' });\n cacheResponse = await this.redisClient.get(cacheKey);\n }\n\n if (cacheResponse) {\n try {\n const { data } = JSON.parse(JSON.parse(cacheResponse)?.value) ?? {};\n const queryName = this.getQueryName(query);\n this.log('debug', `Found cache for ${cacheKey}`);\n return data?.[queryName] ?? null;\n } catch (error) {\n this.log('warn', `Failed to parse cache data for ${cacheKey}:`, error);\n return null;\n }\n }\n\n this.log('debug', `No cache found for key ${cacheKey}`);\n return null;\n }\n\n /**\n * Set cached data for a GraphQL query\n *\n * @param query - GraphQL query\n * @param variables - Query variables\n * @param data - Data to cache\n * @param ctx - Cache context\n * @param cachePolicy - Cache policy (TTL, scope)\n */\n async set<T>(\n query: string | DocumentNode,\n variables: Record<string, unknown>,\n data: T,\n ctx: ICacheContext,\n cachePolicy: ICachePolicy = { maxAge: 86400, scope: 'PUBLIC' },\n ): Promise<void> {\n const cacheKey = this.getCacheKey(query, variables, ctx, cachePolicy);\n const cacheTime = Date.now();\n\n // Ensure maxAge is not negative or zero\n const maxAge = Math.max(1, cachePolicy.maxAge);\n\n if (cachePolicy.maxAge <= 0) {\n this.log(\n 'warn',\n `Invalid maxAge (${cachePolicy.maxAge}) for cache key ${cacheKey}, using minimum value of 1 second`,\n );\n }\n\n this.log('debug', `Set cache for key ${cacheKey} with maxAge ${maxAge}`);\n\n await this.redisClient.set(\n cacheKey,\n JSON.stringify({\n value: JSON.stringify({\n data: { [this.getQueryName(query)]: data },\n cachePolicy: { ...cachePolicy, maxAge },\n cacheTime,\n }),\n expires: cacheTime + maxAge * 1000,\n }).trim(),\n 'EX',\n maxAge,\n );\n }\n\n /**\n * Extract query name from GraphQL query\n */\n private getQueryName(query: string | DocumentNode): string {\n const queryStr = typeof query === 'string' ? query : print(query);\n const [, queryName] = queryStr?.match(/{\\s*(\\w+)/) ?? [];\n return queryName;\n }\n\n /**\n * Build wildcard pattern for query invalidation\n */\n private getWildCardQueryKey(query: string | DocumentNode, ctx?: ICacheContext): string {\n const queryStr = typeof query === 'string' ? query : print(query);\n const [, queryName] = queryStr?.match(/{\\s*(\\w+)/) ?? [];\n const { tenantId } = ctx || {};\n\n // Build pattern without namespace - just APP_NAME:tenantId:segments\n const appName = this.getAppName();\n const sanitizedTenantId = tenantId || 'default';\n return `${appName}:${sanitizedTenantId}:*:${queryName || '*'}:*`;\n }\n\n /**\n * Generate cache key for a GraphQL query\n *\n * Format:\n * - With userId (PRIVATE): APP_NAME:tenantId:userId:queryName:queryHash:variablesHash\n * - Without userId (PUBLIC): APP_NAME:tenantId:queryName:queryHash:variablesHash\n */\n private getCacheKey(\n query: string | DocumentNode,\n variables: Record<string, unknown>,\n ctx?: ICacheContext,\n cachePolicy?: ICachePolicy,\n ): string {\n const appName = this.getAppName();\n\n // Validate tenantId - if it looks like a hash (all hex, 24+ chars), use 'default'\n let tenantId = ctx?.tenantId || 'default';\n if (isHashLikeTenantId(tenantId)) {\n this.log(\n 'warn',\n `TenantId appears to be a hash (${tenantId.substring(0, 16)}...), using \"default\" instead`,\n );\n tenantId = 'default';\n }\n\n // For PUBLIC scope, omit userId to share cache across all users\n // For PRIVATE scope or when not specified, include userId (or 'anonymous')\n const isPublicScope = cachePolicy?.scope === 'PUBLIC';\n const userId = isPublicScope ? undefined : ctx?.userId || 'anonymous';\n\n // Use generateQueryCacheKey with all parameters to avoid duplication\n // This will properly sanitize userId (auth0|123 -> auth0-123) and build the complete key\n return generateQueryCacheKey({\n query,\n variables,\n appName,\n tenantId,\n userId,\n logger: this.logger,\n });\n }\n\n /**\n * Clear all cache entries for a tenant\n */\n async clearTenant(tenantId: string): Promise<number> {\n const appName = this.getAppName();\n const sanitizedTenantId = sanitizeRedisKeyComponent(tenantId);\n const pattern = `${appName}:${sanitizedTenantId}:*`;\n\n return await this.clearPattern(pattern);\n }\n\n /**\n * Clear all cache entries for a user\n */\n async clearUser(userId: string, tenantId?: string): Promise<number> {\n const appName = this.getAppName();\n const sanitizedUserId = sanitizeRedisKeyComponent(userId);\n const sanitizedTenantId = tenantId ? sanitizeRedisKeyComponent(tenantId) : '*';\n const pattern = `${appName}:${sanitizedTenantId}:${sanitizedUserId}:*`;\n\n return await this.clearPattern(pattern);\n }\n\n /**\n * Clear all cache entries matching a pattern\n */\n async clearPattern(pattern: string): Promise<number> {\n this.log('debug', `Clearing cache entries matching pattern: ${pattern}`);\n\n const keys = await this.redisClient.keys(pattern);\n\n if (keys.length === 0) {\n this.log('debug', `No keys found matching pattern: ${pattern}`);\n return 0;\n }\n\n this.log('debug', `Deleting ${keys.length} keys matching pattern: ${pattern}`);\n await this.redisClient.del(...keys);\n\n return keys.length;\n }\n\n /**\n * Get cache statistics\n */\n async getStats(tenantId?: string): Promise<{\n totalKeys: number;\n memoryUsage: number;\n hitRate?: number;\n }> {\n const appName = this.getAppName();\n const pattern = tenantId ? `${appName}:${sanitizeRedisKeyComponent(tenantId)}:*` : `${appName}:*`;\n\n const keys = await this.redisClient.keys(pattern);\n const totalKeys = keys.length;\n\n // Get memory usage for the Redis instance\n let memoryUsage = 0;\n try {\n const info = await this.redisClient.info('memory');\n const match = info.match(/used_memory:(\\d+)/);\n if (match) {\n memoryUsage = parseInt(match[1], 10);\n }\n } catch (error) {\n this.log('warn', 'Failed to get memory info from Redis:', error);\n }\n\n return {\n totalKeys,\n memoryUsage,\n hitRate: undefined, // Hit rate tracking would require additional instrumentation\n };\n }\n\n /**\n * Get application name for key prefix\n * Override this method to provide custom app name\n */\n protected getAppName(): string {\n return process.env.APP_NAME || 'COMMON_STACK';\n }\n\n /**\n * Log helper\n */\n private log(level: string, message: string, ...args: any[]): void {\n if (this.logger && typeof this.logger[level] === 'function') {\n this.logger[level](message, ...args);\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@common-stack/store-redis",
|
|
3
|
-
"version": "8.3.1-alpha.
|
|
3
|
+
"version": "8.3.1-alpha.6",
|
|
4
4
|
"description": "Redis store utilities and services for common-stack",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "CDMBase LLC",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
]
|
|
54
54
|
}
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "fb84350cf08d0ecab5689c99c8cc03e151fd3ace",
|
|
57
57
|
"typescript": {
|
|
58
58
|
"definition": "lib/index.d.ts"
|
|
59
59
|
}
|