@xbg.solutions/utils-cache-connector 1.0.0
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.
- package/lib/cache-connector.d.ts +139 -0
- package/lib/cache-connector.d.ts.map +1 -0
- package/lib/cache-connector.js +277 -0
- package/lib/cache-connector.js.map +1 -0
- package/lib/index.d.ts +52 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +103 -0
- package/lib/index.js.map +1 -0
- package/lib/providers/base-cache-provider.d.ts +95 -0
- package/lib/providers/base-cache-provider.d.ts.map +1 -0
- package/lib/providers/base-cache-provider.js +120 -0
- package/lib/providers/base-cache-provider.js.map +1 -0
- package/lib/providers/firestore-cache-provider.d.ts +58 -0
- package/lib/providers/firestore-cache-provider.d.ts.map +1 -0
- package/lib/providers/firestore-cache-provider.js +418 -0
- package/lib/providers/firestore-cache-provider.js.map +1 -0
- package/lib/providers/memory-cache-provider.d.ts +57 -0
- package/lib/providers/memory-cache-provider.d.ts.map +1 -0
- package/lib/providers/memory-cache-provider.js +217 -0
- package/lib/providers/memory-cache-provider.js.map +1 -0
- package/lib/providers/noop-cache-provider.d.ts +21 -0
- package/lib/providers/noop-cache-provider.d.ts.map +1 -0
- package/lib/providers/noop-cache-provider.js +42 -0
- package/lib/providers/noop-cache-provider.js.map +1 -0
- package/lib/providers/redis-cache-provider.d.ts +64 -0
- package/lib/providers/redis-cache-provider.d.ts.map +1 -0
- package/lib/providers/redis-cache-provider.js +414 -0
- package/lib/providers/redis-cache-provider.js.map +1 -0
- package/lib/types.d.ts +342 -0
- package/lib/types.d.ts.map +1 -0
- package/lib/types.js +8 -0
- package/lib/types.js.map +1 -0
- package/package.json +31 -0
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Redis Cache Provider
|
|
4
|
+
*
|
|
5
|
+
* Redis-based cache provider for high-performance distributed caching.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Sub-10ms response times
|
|
9
|
+
* - Distributed caching across all instances
|
|
10
|
+
* - Pub/sub for distributed invalidation
|
|
11
|
+
* - Advanced data structures (Sets for tags)
|
|
12
|
+
* - Connection pooling
|
|
13
|
+
* - Automatic reconnection
|
|
14
|
+
*
|
|
15
|
+
* Best for:
|
|
16
|
+
* - High-traffic applications (>1M requests/month)
|
|
17
|
+
* - Sub-10ms response time requirements
|
|
18
|
+
* - Large cache sizes exceeding Firestore limits
|
|
19
|
+
* - Advanced caching patterns
|
|
20
|
+
*
|
|
21
|
+
* Trade-offs:
|
|
22
|
+
* - Cost: ~$50/month minimum (Google Cloud Memorystore)
|
|
23
|
+
* - Infrastructure: Requires Redis server
|
|
24
|
+
* - Complexity: Additional service to manage
|
|
25
|
+
*/
|
|
26
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
27
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
|
+
};
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.RedisCacheProvider = void 0;
|
|
31
|
+
const ioredis_1 = __importDefault(require("ioredis"));
|
|
32
|
+
const base_cache_provider_1 = require("./base-cache-provider");
|
|
33
|
+
const utils_logger_1 = require("@xbg/utils-logger");
|
|
34
|
+
class RedisCacheProvider extends base_cache_provider_1.BaseCacheProvider {
|
|
35
|
+
constructor(config) {
|
|
36
|
+
super();
|
|
37
|
+
this.config = config;
|
|
38
|
+
this.isConnected = false;
|
|
39
|
+
// Create Redis client
|
|
40
|
+
this.client = new ioredis_1.default(Object.assign({ host: config.host, port: config.port, password: config.password, db: config.db, connectTimeout: config.connectTimeout || 5000, retryStrategy: (times) => {
|
|
41
|
+
const delay = Math.min(times * 50, 2000);
|
|
42
|
+
return delay;
|
|
43
|
+
} }, (config.tls ? { tls: {} } : {})));
|
|
44
|
+
// Setup event handlers
|
|
45
|
+
this.setupEventHandlers();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Setup Redis event handlers
|
|
49
|
+
*/
|
|
50
|
+
setupEventHandlers() {
|
|
51
|
+
this.client.on('connect', () => {
|
|
52
|
+
this.isConnected = true;
|
|
53
|
+
utils_logger_1.logger.info('Redis cache connected', {
|
|
54
|
+
operation: 'cache.redis.connect',
|
|
55
|
+
host: this.config.host,
|
|
56
|
+
port: this.config.port,
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
this.client.on('error', (error) => {
|
|
60
|
+
utils_logger_1.logger.error('Redis cache error', error, {
|
|
61
|
+
operation: 'cache.redis.error',
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
this.client.on('close', () => {
|
|
65
|
+
this.isConnected = false;
|
|
66
|
+
utils_logger_1.logger.warn('Redis cache connection closed', {
|
|
67
|
+
operation: 'cache.redis.close',
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
this.client.on('reconnecting', () => {
|
|
71
|
+
utils_logger_1.logger.info('Redis cache reconnecting', {
|
|
72
|
+
operation: 'cache.redis.reconnecting',
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
getType() {
|
|
77
|
+
return 'redis';
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Build tag set key
|
|
81
|
+
*/
|
|
82
|
+
buildTagKey(tag) {
|
|
83
|
+
return `cache:tags:${tag}`;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Build metadata key
|
|
87
|
+
*/
|
|
88
|
+
buildMetaKey(key) {
|
|
89
|
+
return `cache:meta:${key}`;
|
|
90
|
+
}
|
|
91
|
+
async get(key) {
|
|
92
|
+
try {
|
|
93
|
+
if (!this.isConnected) {
|
|
94
|
+
this.recordMiss();
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
// Get value and metadata in parallel
|
|
98
|
+
const [valueStr, metaStr] = await Promise.all([
|
|
99
|
+
this.client.get(key),
|
|
100
|
+
this.client.get(this.buildMetaKey(key)),
|
|
101
|
+
]);
|
|
102
|
+
if (!valueStr || !metaStr) {
|
|
103
|
+
this.recordMiss();
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
// Parse metadata
|
|
107
|
+
const meta = JSON.parse(metaStr);
|
|
108
|
+
// Check if expired (shouldn't happen due to Redis TTL, but double-check)
|
|
109
|
+
if (meta.expiresAt < Date.now()) {
|
|
110
|
+
this.recordExpiration();
|
|
111
|
+
this.recordMiss();
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
// Update access metadata (fire and forget)
|
|
115
|
+
this.client
|
|
116
|
+
.set(this.buildMetaKey(key), JSON.stringify(Object.assign(Object.assign({}, meta), { hitCount: meta.hitCount + 1, lastAccessedAt: Date.now() })))
|
|
117
|
+
.catch((error) => {
|
|
118
|
+
utils_logger_1.logger.warn('Failed to update Redis cache metadata', {
|
|
119
|
+
operation: 'cache.redis.updateMeta',
|
|
120
|
+
key,
|
|
121
|
+
error,
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
this.recordHit();
|
|
125
|
+
// Parse and return value
|
|
126
|
+
return JSON.parse(valueStr);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
utils_logger_1.logger.error('Error getting cache entry from Redis', error, {
|
|
130
|
+
operation: 'cache.redis.get',
|
|
131
|
+
key,
|
|
132
|
+
});
|
|
133
|
+
this.recordMiss();
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async getWithMetadata(key) {
|
|
138
|
+
try {
|
|
139
|
+
if (!this.isConnected) {
|
|
140
|
+
this.recordMiss();
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
const [valueStr, metaStr] = await Promise.all([
|
|
144
|
+
this.client.get(key),
|
|
145
|
+
this.client.get(this.buildMetaKey(key)),
|
|
146
|
+
]);
|
|
147
|
+
if (!valueStr || !metaStr) {
|
|
148
|
+
this.recordMiss();
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
const meta = JSON.parse(metaStr);
|
|
152
|
+
// Check if expired
|
|
153
|
+
if (meta.expiresAt < Date.now()) {
|
|
154
|
+
this.recordExpiration();
|
|
155
|
+
this.recordMiss();
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
this.recordHit();
|
|
159
|
+
return {
|
|
160
|
+
key,
|
|
161
|
+
value: JSON.parse(valueStr),
|
|
162
|
+
metadata: {
|
|
163
|
+
createdAt: new Date(meta.createdAt),
|
|
164
|
+
expiresAt: new Date(meta.expiresAt),
|
|
165
|
+
hitCount: meta.hitCount,
|
|
166
|
+
lastAccessedAt: new Date(meta.lastAccessedAt),
|
|
167
|
+
tags: meta.tags,
|
|
168
|
+
size: meta.size,
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
utils_logger_1.logger.error('Error getting cache entry with metadata from Redis', error, {
|
|
174
|
+
operation: 'cache.redis.getWithMetadata',
|
|
175
|
+
key,
|
|
176
|
+
});
|
|
177
|
+
this.recordMiss();
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
async set(key, value, options = {}) {
|
|
182
|
+
try {
|
|
183
|
+
if (!this.isConnected) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const ttl = options.ttl || 300; // Default 5 minutes
|
|
187
|
+
const tags = options.tags || [];
|
|
188
|
+
const size = this.estimateSize(value);
|
|
189
|
+
const now = Date.now();
|
|
190
|
+
const expiresAt = now + ttl * 1000;
|
|
191
|
+
const meta = {
|
|
192
|
+
createdAt: now,
|
|
193
|
+
expiresAt,
|
|
194
|
+
hitCount: 0,
|
|
195
|
+
lastAccessedAt: now,
|
|
196
|
+
tags,
|
|
197
|
+
size,
|
|
198
|
+
};
|
|
199
|
+
// Use pipeline for atomic operations
|
|
200
|
+
const pipeline = this.client.pipeline();
|
|
201
|
+
// Set value with TTL
|
|
202
|
+
pipeline.set(key, JSON.stringify(value), 'EX', ttl);
|
|
203
|
+
// Set metadata with TTL
|
|
204
|
+
pipeline.set(this.buildMetaKey(key), JSON.stringify(meta), 'EX', ttl);
|
|
205
|
+
// Add key to tag sets
|
|
206
|
+
for (const tag of tags) {
|
|
207
|
+
pipeline.sadd(this.buildTagKey(tag), key);
|
|
208
|
+
// Set expiry on tag set (slightly longer than cache TTL)
|
|
209
|
+
pipeline.expire(this.buildTagKey(tag), ttl + 60);
|
|
210
|
+
}
|
|
211
|
+
await pipeline.exec();
|
|
212
|
+
}
|
|
213
|
+
catch (error) {
|
|
214
|
+
utils_logger_1.logger.error('Error setting cache entry in Redis', error, {
|
|
215
|
+
operation: 'cache.redis.set',
|
|
216
|
+
key,
|
|
217
|
+
ttl: options.ttl,
|
|
218
|
+
});
|
|
219
|
+
throw error;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
async delete(key) {
|
|
223
|
+
var _a;
|
|
224
|
+
try {
|
|
225
|
+
if (!this.isConnected) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
// Get metadata to find tags
|
|
229
|
+
const metaStr = await this.client.get(this.buildMetaKey(key));
|
|
230
|
+
const pipeline = this.client.pipeline();
|
|
231
|
+
// Delete value and metadata
|
|
232
|
+
pipeline.del(key);
|
|
233
|
+
pipeline.del(this.buildMetaKey(key));
|
|
234
|
+
// Remove from tag sets
|
|
235
|
+
if (metaStr) {
|
|
236
|
+
const meta = JSON.parse(metaStr);
|
|
237
|
+
for (const tag of meta.tags) {
|
|
238
|
+
pipeline.srem(this.buildTagKey(tag), key);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const results = await pipeline.exec();
|
|
242
|
+
// Check if value was deleted (first operation)
|
|
243
|
+
return ((_a = results === null || results === void 0 ? void 0 : results[0]) === null || _a === void 0 ? void 0 : _a[1]) === 1;
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
utils_logger_1.logger.error('Error deleting cache entry from Redis', error, {
|
|
247
|
+
operation: 'cache.redis.delete',
|
|
248
|
+
key,
|
|
249
|
+
});
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
async has(key) {
|
|
254
|
+
try {
|
|
255
|
+
if (!this.isConnected) {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
const exists = await this.client.exists(key);
|
|
259
|
+
return exists === 1;
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
utils_logger_1.logger.error('Error checking cache entry in Redis', error, {
|
|
263
|
+
operation: 'cache.redis.has',
|
|
264
|
+
key,
|
|
265
|
+
});
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
async invalidateByTags(tags) {
|
|
270
|
+
try {
|
|
271
|
+
if (!this.isConnected) {
|
|
272
|
+
return 0;
|
|
273
|
+
}
|
|
274
|
+
let count = 0;
|
|
275
|
+
for (const tag of tags) {
|
|
276
|
+
const tagKey = this.buildTagKey(tag);
|
|
277
|
+
// Get all keys with this tag
|
|
278
|
+
const keys = await this.client.smembers(tagKey);
|
|
279
|
+
if (keys.length === 0) {
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
// Delete all keys and their metadata
|
|
283
|
+
const pipeline = this.client.pipeline();
|
|
284
|
+
for (const key of keys) {
|
|
285
|
+
pipeline.del(key);
|
|
286
|
+
pipeline.del(this.buildMetaKey(key));
|
|
287
|
+
}
|
|
288
|
+
// Delete the tag set itself
|
|
289
|
+
pipeline.del(tagKey);
|
|
290
|
+
await pipeline.exec();
|
|
291
|
+
count += keys.length;
|
|
292
|
+
}
|
|
293
|
+
return count;
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
utils_logger_1.logger.error('Error invalidating cache by tags in Redis', error, {
|
|
297
|
+
operation: 'cache.redis.invalidateByTags',
|
|
298
|
+
tags,
|
|
299
|
+
});
|
|
300
|
+
return 0;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
async invalidateByPattern(pattern, mode = 'prefix') {
|
|
304
|
+
try {
|
|
305
|
+
if (!this.isConnected) {
|
|
306
|
+
return 0;
|
|
307
|
+
}
|
|
308
|
+
// Build Redis pattern based on mode
|
|
309
|
+
let redisPattern;
|
|
310
|
+
switch (mode) {
|
|
311
|
+
case 'prefix':
|
|
312
|
+
redisPattern = `${pattern}*`;
|
|
313
|
+
break;
|
|
314
|
+
case 'suffix':
|
|
315
|
+
redisPattern = `*${pattern}`;
|
|
316
|
+
break;
|
|
317
|
+
case 'contains':
|
|
318
|
+
redisPattern = `*${pattern}*`;
|
|
319
|
+
break;
|
|
320
|
+
default:
|
|
321
|
+
redisPattern = pattern;
|
|
322
|
+
}
|
|
323
|
+
const keys = [];
|
|
324
|
+
let cursor = '0';
|
|
325
|
+
// Use SCAN to iterate through keys (safer than KEYS for production)
|
|
326
|
+
do {
|
|
327
|
+
const result = await this.client.scan(cursor, 'MATCH', redisPattern, 'COUNT', 100);
|
|
328
|
+
cursor = result[0];
|
|
329
|
+
keys.push(...result[1]);
|
|
330
|
+
} while (cursor !== '0');
|
|
331
|
+
if (keys.length === 0) {
|
|
332
|
+
return 0;
|
|
333
|
+
}
|
|
334
|
+
// Delete matched keys and their metadata
|
|
335
|
+
const pipeline = this.client.pipeline();
|
|
336
|
+
for (const key of keys) {
|
|
337
|
+
// Don't delete metadata or tag keys
|
|
338
|
+
if (!key.startsWith('cache:meta:') && !key.startsWith('cache:tags:')) {
|
|
339
|
+
pipeline.del(key);
|
|
340
|
+
pipeline.del(this.buildMetaKey(key));
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
await pipeline.exec();
|
|
344
|
+
return keys.length;
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
utils_logger_1.logger.error('Error invalidating cache by pattern in Redis', error, {
|
|
348
|
+
operation: 'cache.redis.invalidateByPattern',
|
|
349
|
+
pattern,
|
|
350
|
+
mode,
|
|
351
|
+
});
|
|
352
|
+
return 0;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
async clear() {
|
|
356
|
+
try {
|
|
357
|
+
if (!this.isConnected) {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
// Clear all keys in the current database
|
|
361
|
+
await this.client.flushdb();
|
|
362
|
+
utils_logger_1.logger.info('Redis cache cleared', {
|
|
363
|
+
operation: 'cache.redis.clear',
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
utils_logger_1.logger.error('Error clearing cache in Redis', error, {
|
|
368
|
+
operation: 'cache.redis.clear',
|
|
369
|
+
});
|
|
370
|
+
throw error;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
async cleanup() {
|
|
374
|
+
// Redis handles TTL expiration automatically
|
|
375
|
+
// This method is a no-op for Redis
|
|
376
|
+
return 0;
|
|
377
|
+
}
|
|
378
|
+
async getStats() {
|
|
379
|
+
try {
|
|
380
|
+
if (!this.isConnected) {
|
|
381
|
+
return super.getStats();
|
|
382
|
+
}
|
|
383
|
+
// Get Redis keyspace info
|
|
384
|
+
const keyspace = await this.client.info('keyspace');
|
|
385
|
+
// Parse keyspace info
|
|
386
|
+
const dbMatch = keyspace.match(/db\d+:keys=(\d+)/);
|
|
387
|
+
const keyCount = dbMatch ? parseInt(dbMatch[1], 10) : 0;
|
|
388
|
+
this.updateEntryCount(keyCount);
|
|
389
|
+
return super.getStats();
|
|
390
|
+
}
|
|
391
|
+
catch (error) {
|
|
392
|
+
utils_logger_1.logger.error('Error getting cache stats from Redis', error, {
|
|
393
|
+
operation: 'cache.redis.getStats',
|
|
394
|
+
});
|
|
395
|
+
return super.getStats();
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Check if Redis is connected
|
|
400
|
+
*/
|
|
401
|
+
isReady() {
|
|
402
|
+
return this.isConnected;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Cleanup on provider destruction
|
|
406
|
+
*/
|
|
407
|
+
destroy() {
|
|
408
|
+
if (this.client) {
|
|
409
|
+
this.client.disconnect();
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
exports.RedisCacheProvider = RedisCacheProvider;
|
|
414
|
+
//# sourceMappingURL=redis-cache-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-cache-provider.js","sourceRoot":"","sources":["../../src/providers/redis-cache-provider.ts"],"names":[],"mappings":"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"}
|