@bernierllc/cache-manager 1.0.1

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.
Files changed (62) hide show
  1. package/README.md +425 -0
  2. package/dist/backends/index.d.ts +4 -0
  3. package/dist/backends/index.d.ts.map +1 -0
  4. package/dist/backends/index.js +27 -0
  5. package/dist/backends/index.js.map +1 -0
  6. package/dist/backends/memory.d.ts +21 -0
  7. package/dist/backends/memory.d.ts.map +1 -0
  8. package/dist/backends/memory.js +136 -0
  9. package/dist/backends/memory.js.map +1 -0
  10. package/dist/backends/multi-tier.d.ts +17 -0
  11. package/dist/backends/multi-tier.d.ts.map +1 -0
  12. package/dist/backends/multi-tier.js +150 -0
  13. package/dist/backends/multi-tier.js.map +1 -0
  14. package/dist/backends/redis.d.ts +18 -0
  15. package/dist/backends/redis.d.ts.map +1 -0
  16. package/dist/backends/redis.js +166 -0
  17. package/dist/backends/redis.js.map +1 -0
  18. package/dist/constants.d.ts +22 -0
  19. package/dist/constants.d.ts.map +1 -0
  20. package/dist/constants.js +32 -0
  21. package/dist/constants.js.map +1 -0
  22. package/dist/index.d.ts +7 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +34 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/manager.d.ts +26 -0
  27. package/dist/manager.d.ts.map +1 -0
  28. package/dist/manager.js +171 -0
  29. package/dist/manager.js.map +1 -0
  30. package/dist/serializers/binary.d.ts +6 -0
  31. package/dist/serializers/binary.d.ts.map +1 -0
  32. package/dist/serializers/binary.js +22 -0
  33. package/dist/serializers/binary.js.map +1 -0
  34. package/dist/serializers/index.d.ts +3 -0
  35. package/dist/serializers/index.d.ts.map +1 -0
  36. package/dist/serializers/index.js +26 -0
  37. package/dist/serializers/index.js.map +1 -0
  38. package/dist/serializers/json.d.ts +6 -0
  39. package/dist/serializers/json.d.ts.map +1 -0
  40. package/dist/serializers/json.js +20 -0
  41. package/dist/serializers/json.js.map +1 -0
  42. package/dist/strategies/index.d.ts +6 -0
  43. package/dist/strategies/index.d.ts.map +1 -0
  44. package/dist/strategies/index.js +41 -0
  45. package/dist/strategies/index.js.map +1 -0
  46. package/dist/strategies/lfu.d.ts +10 -0
  47. package/dist/strategies/lfu.d.ts.map +1 -0
  48. package/dist/strategies/lfu.js +43 -0
  49. package/dist/strategies/lfu.js.map +1 -0
  50. package/dist/strategies/lru.d.ts +11 -0
  51. package/dist/strategies/lru.d.ts.map +1 -0
  52. package/dist/strategies/lru.js +48 -0
  53. package/dist/strategies/lru.js.map +1 -0
  54. package/dist/strategies/ttl.d.ts +9 -0
  55. package/dist/strategies/ttl.d.ts.map +1 -0
  56. package/dist/strategies/ttl.js +47 -0
  57. package/dist/strategies/ttl.js.map +1 -0
  58. package/dist/types.d.ts +73 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +10 -0
  61. package/dist/types.js.map +1 -0
  62. package/package.json +65 -0
package/README.md ADDED
@@ -0,0 +1,425 @@
1
+ # @bernierllc/cache-manager
2
+
3
+ Multi-tier caching with TTL support, cache invalidation, and multiple storage backends.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @bernierllc/cache-manager
9
+ ```
10
+
11
+ For Redis support:
12
+ ```bash
13
+ npm install @bernierllc/cache-manager redis
14
+ ```
15
+
16
+ ## Quick Start
17
+
18
+ ```typescript
19
+ import { CacheManager } from '@bernierllc/cache-manager';
20
+
21
+ // Create cache with default memory backend
22
+ const cache = new CacheManager({
23
+ strategy: 'lru',
24
+ maxSize: 1000,
25
+ defaultTtl: 60 * 1000 // 1 minute
26
+ });
27
+
28
+ // Set cache value
29
+ await cache.set('user:123', { name: 'John', email: 'john@example.com' });
30
+
31
+ // Get cache value
32
+ const user = await cache.get('user:123');
33
+ console.log(user); // { name: 'John', email: 'john@example.com' }
34
+
35
+ // Get or set pattern
36
+ const userData = await cache.getOrSet('user:456', async () => {
37
+ return await fetchUserFromDatabase('456');
38
+ }, 5 * 60 * 1000); // Cache for 5 minutes
39
+ ```
40
+
41
+ ## Core Features
42
+
43
+ - **Multiple Backends**: Memory, Redis, database, multi-tier
44
+ - **Cache Strategies**: LRU, LFU, TTL-based eviction policies
45
+ - **Intelligent Invalidation**: Tag-based, pattern-based cache invalidation
46
+ - **Serialization**: JSON, binary, custom serializers
47
+ - **Compression**: Optional compression for large values
48
+ - **Stats & Monitoring**: Hit rates, memory usage, performance metrics
49
+ - **Distributed Support**: Redis-backed distributed caching
50
+
51
+ ## API Reference
52
+
53
+ ### CacheManager
54
+
55
+ #### Constructor
56
+
57
+ ```typescript
58
+ const cache = new CacheManager(options: CacheOptions)
59
+ ```
60
+
61
+ **Options:**
62
+ - `backend?: CacheBackend | CacheBackend[]` - Storage backend(s)
63
+ - `strategy?: 'lru' | 'lfu' | 'ttl'` - Eviction strategy (default: 'lru')
64
+ - `maxSize?: number` - Maximum cache size (default: 1000)
65
+ - `defaultTtl?: number` - Default TTL in milliseconds
66
+ - `keyPrefix?: string` - Prefix for all cache keys
67
+ - `onEviction?: (key, value) => void` - Eviction callback
68
+ - `onExpiration?: (key, value) => void` - Expiration callback
69
+
70
+ #### Core Methods
71
+
72
+ ```typescript
73
+ // Basic operations
74
+ await cache.set(key: string, value: any, ttl?: number, tags?: string[]): Promise<void>
75
+ await cache.get<T>(key: string): Promise<T | null>
76
+ await cache.delete(key: string): Promise<boolean>
77
+ await cache.clear(): Promise<void>
78
+ await cache.has(key: string): Promise<boolean>
79
+
80
+ // Batch operations
81
+ await cache.mget<T>(keys: string[]): Promise<(T | null)[]>
82
+ await cache.mset<T>(entries: Record<string, T>, ttl?: number): Promise<void>
83
+ await cache.getOrSet<T>(key: string, factory: () => Promise<T>, ttl?: number): Promise<T>
84
+
85
+ // Invalidation
86
+ await cache.invalidateByTag(tag: string): Promise<void>
87
+ await cache.invalidateByPattern(pattern: string): Promise<void>
88
+
89
+ // Utilities
90
+ await cache.keys(pattern?: string): Promise<string[]>
91
+ await cache.size(): Promise<number>
92
+ await cache.getStats(): Promise<CacheStats>
93
+ await cache.cleanup(): Promise<number>
94
+ ```
95
+
96
+ ## Usage Examples
97
+
98
+ ### Basic Memory Caching
99
+
100
+ ```typescript
101
+ import { CacheManager, MemoryCacheBackend } from '@bernierllc/cache-manager';
102
+
103
+ const cache = new CacheManager({
104
+ backend: new MemoryCacheBackend({
105
+ maxSize: 1000,
106
+ strategy: 'lru'
107
+ }),
108
+ defaultTtl: 60 * 60 * 1000 // 1 hour
109
+ });
110
+
111
+ // Cache user data
112
+ await cache.set('user:123', {
113
+ name: 'John Doe',
114
+ email: 'john@example.com'
115
+ });
116
+
117
+ const user = await cache.get('user:123');
118
+ console.log(user.name); // 'John Doe'
119
+ ```
120
+
121
+ ### Redis-backed Distributed Cache
122
+
123
+ ```typescript
124
+ import { CacheManager, RedisCacheBackend } from '@bernierllc/cache-manager';
125
+
126
+ const cache = new CacheManager({
127
+ backend: new RedisCacheBackend({
128
+ host: 'localhost',
129
+ port: 6379,
130
+ keyPrefix: 'myapp:'
131
+ }),
132
+ defaultTtl: 15 * 60 * 1000 // 15 minutes
133
+ });
134
+
135
+ // Works across multiple application instances
136
+ await cache.set('global:config', configObject);
137
+ ```
138
+
139
+ ### Multi-tier Caching
140
+
141
+ ```typescript
142
+ import {
143
+ CacheManager,
144
+ MemoryCacheBackend,
145
+ RedisCacheBackend
146
+ } from '@bernierllc/cache-manager';
147
+
148
+ const cache = new CacheManager({
149
+ backend: [
150
+ new MemoryCacheBackend({ maxSize: 100 }), // L1 cache - fast, small
151
+ new RedisCacheBackend({ host: 'localhost' }) // L2 cache - shared, persistent
152
+ ]
153
+ });
154
+
155
+ // Automatically checks L1, then L2, updates L1 on L2 hits
156
+ const data = await cache.get('expensive:computation');
157
+ ```
158
+
159
+ ### Tag-based Invalidation
160
+
161
+ ```typescript
162
+ const cache = new CacheManager({
163
+ backend: new RedisCacheBackend({ host: 'localhost' })
164
+ });
165
+
166
+ // Cache with tags
167
+ await cache.set('post:1', postData, 60 * 60 * 1000, ['user:123', 'category:tech']);
168
+ await cache.set('post:2', postData2, 60 * 60 * 1000, ['user:123', 'category:news']);
169
+
170
+ // Invalidate all posts by user
171
+ await cache.invalidateByTag('user:123');
172
+
173
+ // Invalidate all tech posts
174
+ await cache.invalidateByTag('category:tech');
175
+ ```
176
+
177
+ ### Pattern-based Invalidation
178
+
179
+ ```typescript
180
+ // Cache user-specific data
181
+ await cache.set('user:123:profile', profileData);
182
+ await cache.set('user:123:settings', settingsData);
183
+ await cache.set('user:456:profile', otherProfileData);
184
+
185
+ // Invalidate all data for user 123
186
+ await cache.invalidateByPattern('user:123:*');
187
+ ```
188
+
189
+ ### Cache Warming and Preloading
190
+
191
+ ```typescript
192
+ // Warm cache with frequently accessed data
193
+ async function warmCache() {
194
+ const popularUsers = await getPopularUsers();
195
+
196
+ for (const user of popularUsers) {
197
+ await cache.set(`user:${user.id}`, user, 60 * 60 * 1000);
198
+ }
199
+ }
200
+
201
+ // Background cache refresh
202
+ setInterval(async () => {
203
+ const keys = await cache.keys('user:*');
204
+
205
+ for (const key of keys) {
206
+ const userId = key.split(':')[1];
207
+ const freshData = await fetchUserFromDatabase(userId);
208
+ await cache.set(key, freshData, 60 * 60 * 1000);
209
+ }
210
+ }, 30 * 60 * 1000); // Refresh every 30 minutes
211
+ ```
212
+
213
+ ### Performance Monitoring
214
+
215
+ ```typescript
216
+ // Monitor cache performance
217
+ setInterval(async () => {
218
+ const stats = await cache.getStats();
219
+
220
+ console.log(`Cache Performance:
221
+ Hit Rate: ${(stats.hitRate * 100).toFixed(1)}%
222
+ Size: ${stats.size} entries
223
+ Memory: ${Math.round(stats.memoryUsage / 1024)}KB
224
+ Evictions: ${stats.evictions}
225
+ `);
226
+ }, 60000);
227
+
228
+ // Automatic cleanup
229
+ cache.startCleanupInterval(5 * 60 * 1000); // Clean every 5 minutes
230
+ ```
231
+
232
+ ## Configuration
233
+
234
+ ### Cache Backends
235
+
236
+ #### MemoryCacheBackend
237
+ ```typescript
238
+ new MemoryCacheBackend({
239
+ maxSize: 1000, // Maximum number of entries
240
+ strategy: 'lru', // Eviction strategy
241
+ onEviction: (key, value) => console.log('Evicted:', key),
242
+ onExpiration: (key, value) => console.log('Expired:', key)
243
+ })
244
+ ```
245
+
246
+ #### RedisCacheBackend
247
+ ```typescript
248
+ new RedisCacheBackend({
249
+ host: 'localhost',
250
+ port: 6379,
251
+ password: 'secret', // Optional
252
+ db: 0, // Database number
253
+ keyPrefix: 'cache:', // Key prefix
254
+ connectionString: 'redis://localhost:6379' // Alternative to host/port
255
+ })
256
+ ```
257
+
258
+ #### MultiTierCacheBackend
259
+ ```typescript
260
+ new MultiTierCacheBackend({
261
+ backends: [
262
+ new MemoryCacheBackend({ maxSize: 100 }),
263
+ new RedisCacheBackend({ host: 'localhost' })
264
+ ]
265
+ })
266
+ ```
267
+
268
+ ### Cache Strategies
269
+
270
+ - **LRU (Least Recently Used)**: Evicts the least recently accessed entries
271
+ - **LFU (Least Frequently Used)**: Evicts the least frequently accessed entries
272
+ - **TTL (Time To Live)**: Evicts entries based on expiration time
273
+
274
+ ### Serializers
275
+
276
+ ```typescript
277
+ import { JSONSerializer, BinarySerializer } from '@bernierllc/cache-manager';
278
+
279
+ // JSON serialization (default)
280
+ const cache = new CacheManager({
281
+ serializer: new JSONSerializer()
282
+ });
283
+
284
+ // Binary serialization for better performance
285
+ const cache = new CacheManager({
286
+ serializer: new BinarySerializer()
287
+ });
288
+ ```
289
+
290
+ ## Error Handling
291
+
292
+ ```typescript
293
+ try {
294
+ await cache.set('key', 'value');
295
+ const value = await cache.get('key');
296
+ } catch (error) {
297
+ console.error('Cache operation failed:', error);
298
+ // Fallback to original data source
299
+ }
300
+ ```
301
+
302
+ ## Best Practices
303
+
304
+ 1. **Choose appropriate TTL**: Set TTL based on data freshness requirements
305
+ 2. **Use appropriate cache size**: Balance memory usage with hit rates
306
+ 3. **Implement cache warming**: Preload frequently accessed data
307
+ 4. **Monitor performance**: Track hit rates and adjust configuration
308
+ 5. **Handle failures gracefully**: Always have fallback mechanisms
309
+ 6. **Use tags wisely**: Group related cache entries for efficient invalidation
310
+
311
+ ## Performance
312
+
313
+ The cache manager is designed for high-performance scenarios:
314
+
315
+ - **Memory backend**: >50,000 operations/second
316
+ - **Redis backend**: >10,000 operations/second
317
+ - **Multi-tier**: Combines speed of memory with persistence of Redis
318
+ - **Efficient serialization**: Minimal overhead for data conversion
319
+ - **Smart eviction**: Algorithms optimized for real-world usage patterns
320
+
321
+ ## Integration Documentation
322
+
323
+ ### Logger Integration
324
+
325
+ The cache manager supports optional logger integration using `@bernierllc/logger`:
326
+
327
+ ```typescript
328
+ import { CacheManager } from '@bernierllc/cache-manager';
329
+ import { detectLogger } from '@bernierllc/logger';
330
+
331
+ const cache = new CacheManager({
332
+ strategy: 'lru',
333
+ maxSize: 1000
334
+ });
335
+
336
+ // Auto-detect logger if available
337
+ const logger = await detectLogger();
338
+ if (logger) {
339
+ // Enhanced logging for cache operations
340
+ cache.on('hit', (key) => {
341
+ logger.debug('Cache hit', { key });
342
+ });
343
+
344
+ cache.on('miss', (key) => {
345
+ logger.debug('Cache miss', { key });
346
+ });
347
+
348
+ cache.on('evicted', (key, reason) => {
349
+ logger.info('Cache eviction', { key, reason });
350
+ });
351
+ }
352
+ ```
353
+
354
+ ### NeverHub Integration
355
+
356
+ The cache manager integrates with NeverHub when available for enhanced service discovery and monitoring:
357
+
358
+ ```typescript
359
+ import { CacheManager } from '@bernierllc/cache-manager';
360
+ import { detectNeverHub } from '@bernierllc/neverhub-adapter';
361
+
362
+ async function initializeCacheManager() {
363
+ const cache = new CacheManager({
364
+ strategy: 'lru',
365
+ maxSize: 1000
366
+ });
367
+
368
+ // Auto-detect NeverHub
369
+ const neverhub = await detectNeverHub();
370
+ if (neverhub) {
371
+ // Register cache manager as a service
372
+ await neverhub.register({
373
+ type: 'cache-manager',
374
+ name: '@bernierllc/cache-manager',
375
+ version: '1.0.0',
376
+ capabilities: [
377
+ { type: 'cache', name: 'memory', version: '1.0.0' },
378
+ { type: 'cache', name: 'redis', version: '1.0.0' }
379
+ ]
380
+ });
381
+
382
+ // Publish cache events
383
+ cache.on('hit', async (key) => {
384
+ await neverhub.publishEvent({
385
+ type: 'cache.hit',
386
+ data: { key, timestamp: Date.now() }
387
+ });
388
+ });
389
+
390
+ // Subscribe to cache invalidation events
391
+ await neverhub.subscribe('cache.invalidate', async (event) => {
392
+ if (event.data.pattern) {
393
+ await cache.invalidatePattern(event.data.pattern);
394
+ } else if (event.data.key) {
395
+ await cache.delete(event.data.key);
396
+ }
397
+ });
398
+ }
399
+
400
+ return cache;
401
+ }
402
+ ```
403
+
404
+ ### Graceful Degradation
405
+
406
+ The cache manager implements graceful degradation patterns:
407
+
408
+ - **Works without external services**: Core functionality operates independently
409
+ - **Logger integration**: Enhanced monitoring when logger service is available
410
+ - **NeverHub integration**: Service discovery and events when NeverHub is present
411
+ - **Backend flexibility**: Falls back to memory storage if Redis is unavailable
412
+ - **Error resilience**: Cache failures don't break application functionality
413
+
414
+ ## Dependencies
415
+
416
+ - **Required**: None (core functionality)
417
+ - **Optional**: `redis` for Redis backend support
418
+ - **Optional**: `lz4` for compression support
419
+ - **Optional**: `@bernierllc/logger` for enhanced logging capabilities
420
+ - **Optional**: `@bernierllc/neverhub-adapter` for service discovery integration
421
+ - **Internal**: `@bernierllc/connection-parser` for connection string parsing
422
+
423
+ ## License
424
+
425
+ Copyright (c) 2025 Bernier LLC. All rights reserved.
@@ -0,0 +1,4 @@
1
+ export * from './memory';
2
+ export * from './redis';
3
+ export * from './multi-tier';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":"AAQA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC"}
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ var desc = Object.getOwnPropertyDescriptor(m, k);
12
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
13
+ desc = { enumerable: true, get: function() { return m[k]; } };
14
+ }
15
+ Object.defineProperty(o, k2, desc);
16
+ }) : (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ o[k2] = m[k];
19
+ }));
20
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
21
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ __exportStar(require("./memory"), exports);
25
+ __exportStar(require("./redis"), exports);
26
+ __exportStar(require("./multi-tier"), exports);
27
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/backends/index.ts"],"names":[],"mappings":";AAAA;;;;;;EAME;;;;;;;;;;;;;;;;AAEF,2CAAyB;AACzB,0CAAwB;AACxB,+CAA6B"}
@@ -0,0 +1,21 @@
1
+ import type { CacheBackend, CacheEntry, CacheStats, MemoryCacheOptions } from '../types';
2
+ export declare class MemoryCacheBackend implements CacheBackend {
3
+ private cache;
4
+ private strategy;
5
+ private maxSize;
6
+ private options;
7
+ private stats;
8
+ constructor(options?: MemoryCacheOptions);
9
+ get<T>(key: string): Promise<CacheEntry<T> | null>;
10
+ set<T>(key: string, entry: CacheEntry<T>, ttl?: number): Promise<void>;
11
+ private evictLeastImportant;
12
+ delete(key: string): Promise<boolean>;
13
+ clear(): Promise<void>;
14
+ keys(pattern?: string): Promise<string[]>;
15
+ size(): Promise<number>;
16
+ getStats(): Promise<CacheStats>;
17
+ private updateHitRate;
18
+ private updateStats;
19
+ private calculateMemoryUsage;
20
+ }
21
+ //# sourceMappingURL=memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/backends/memory.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAiB,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAIxG,qBAAa,kBAAmB,YAAW,YAAY;IACrD,OAAO,CAAC,KAAK,CAAiC;IAC9C,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,KAAK,CAQX;gBAEU,OAAO,GAAE,kBAAuB;IAMtC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAoClD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAkB9D,mBAAmB;IAc3B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAMtB,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAYzC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAIvB,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC;IAIrC,OAAO,CAAC,aAAa;IAKrB,OAAO,CAAC,WAAW;IAKnB,OAAO,CAAC,oBAAoB;CAuB7B"}
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ /*
3
+ Copyright (c) 2025 Bernier LLC
4
+
5
+ This file is licensed to the client under a limited-use license.
6
+ The client may use and modify this code *only within the scope of the project it was delivered for*.
7
+ Redistribution or use in other products or commercial offerings is not permitted without written consent from Bernier LLC.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.MemoryCacheBackend = void 0;
11
+ const strategies_1 = require("../strategies");
12
+ const constants_1 = require("../constants");
13
+ class MemoryCacheBackend {
14
+ constructor(options = {}) {
15
+ this.cache = new Map();
16
+ this.stats = {
17
+ hits: 0,
18
+ misses: 0,
19
+ hitRate: 0,
20
+ size: 0,
21
+ memoryUsage: 0,
22
+ evictions: 0,
23
+ expirations: 0
24
+ };
25
+ this.options = options;
26
+ this.maxSize = options.maxSize || constants_1.DEFAULT_CACHE_OPTIONS.maxSize;
27
+ this.strategy = (0, strategies_1.createStrategy)(options.strategy || constants_1.DEFAULT_CACHE_OPTIONS.strategy);
28
+ }
29
+ async get(key) {
30
+ const entry = this.cache.get(key);
31
+ if (!entry) {
32
+ this.stats.misses++;
33
+ this.updateHitRate();
34
+ return null;
35
+ }
36
+ // Check if expired
37
+ if (entry.expiresAt && entry.expiresAt < new Date()) {
38
+ this.cache.delete(key);
39
+ this.stats.expirations++;
40
+ this.stats.misses++;
41
+ this.updateHitRate();
42
+ if (this.options.onExpiration) {
43
+ this.options.onExpiration(key, entry.value);
44
+ }
45
+ return null;
46
+ }
47
+ // Update access information
48
+ entry.accessedAt = new Date();
49
+ entry.accessCount++;
50
+ // Update strategy
51
+ this.strategy.recordAccess(key, entry);
52
+ this.stats.hits++;
53
+ this.updateHitRate();
54
+ return entry;
55
+ }
56
+ async set(key, entry, ttl) {
57
+ // Set expiration if TTL provided
58
+ if (ttl) {
59
+ entry.expiresAt = new Date(Date.now() + ttl);
60
+ }
61
+ // Check if we need to evict
62
+ if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
63
+ await this.evictLeastImportant();
64
+ }
65
+ // Store entry
66
+ this.cache.set(key, entry);
67
+ this.strategy.recordSet(key, entry);
68
+ this.updateStats();
69
+ }
70
+ async evictLeastImportant() {
71
+ const keyToEvict = this.strategy.selectForEviction(this.cache);
72
+ if (keyToEvict) {
73
+ const entry = this.cache.get(keyToEvict);
74
+ this.cache.delete(keyToEvict);
75
+ this.stats.evictions++;
76
+ if (entry && this.options.onEviction) {
77
+ this.options.onEviction(keyToEvict, entry.value);
78
+ }
79
+ }
80
+ }
81
+ async delete(key) {
82
+ const existed = this.cache.delete(key);
83
+ this.strategy.recordDelete(key);
84
+ this.updateStats();
85
+ return existed;
86
+ }
87
+ async clear() {
88
+ this.cache.clear();
89
+ this.strategy.clear();
90
+ this.updateStats();
91
+ }
92
+ async keys(pattern) {
93
+ const allKeys = Array.from(this.cache.keys());
94
+ if (!pattern) {
95
+ return allKeys;
96
+ }
97
+ // Simple pattern matching (* wildcard)
98
+ const regex = new RegExp(pattern.replace(/\*/g, '.*'));
99
+ return allKeys.filter(key => regex.test(key));
100
+ }
101
+ async size() {
102
+ return this.cache.size;
103
+ }
104
+ async getStats() {
105
+ return { ...this.stats };
106
+ }
107
+ updateHitRate() {
108
+ const total = this.stats.hits + this.stats.misses;
109
+ this.stats.hitRate = total > 0 ? this.stats.hits / total : 0;
110
+ }
111
+ updateStats() {
112
+ this.stats.size = this.cache.size;
113
+ this.stats.memoryUsage = this.calculateMemoryUsage();
114
+ }
115
+ calculateMemoryUsage() {
116
+ let totalSize = 0;
117
+ const keys = Array.from(this.cache.keys());
118
+ // Sample a subset for large caches
119
+ const sampleSize = Math.min(keys.length, Math.max(10, Math.floor(keys.length * constants_1.MEMORY_USAGE_SAMPLE_RATE)));
120
+ const sampleKeys = keys.slice(0, sampleSize);
121
+ for (const key of sampleKeys) {
122
+ const entry = this.cache.get(key);
123
+ if (entry) {
124
+ totalSize += Buffer.byteLength(key, 'utf8');
125
+ totalSize += Buffer.byteLength(JSON.stringify(entry.value), 'utf8');
126
+ }
127
+ }
128
+ // Extrapolate to full cache size
129
+ if (sampleSize > 0 && keys.length > sampleSize) {
130
+ totalSize = Math.round((totalSize / sampleSize) * keys.length);
131
+ }
132
+ return totalSize;
133
+ }
134
+ }
135
+ exports.MemoryCacheBackend = MemoryCacheBackend;
136
+ //# sourceMappingURL=memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/backends/memory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { CacheBackend, CacheEntry, CacheStats, MultiTierCacheOptions } from '../types';
2
+ export declare class MultiTierCacheBackend implements CacheBackend {
3
+ private backends;
4
+ private stats;
5
+ constructor(options: MultiTierCacheOptions);
6
+ get<T>(key: string): Promise<CacheEntry<T> | null>;
7
+ set<T>(key: string, entry: CacheEntry<T>, ttl?: number): Promise<void>;
8
+ delete(key: string): Promise<boolean>;
9
+ clear(): Promise<void>;
10
+ keys(pattern?: string): Promise<string[]>;
11
+ size(): Promise<number>;
12
+ getStats(): Promise<CacheStats>;
13
+ private updateHitRate;
14
+ getBackendCount(): number;
15
+ getBackendStats(index: number): Promise<CacheStats | null>;
16
+ }
17
+ //# sourceMappingURL=multi-tier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multi-tier.d.ts","sourceRoot":"","sources":["../../src/backends/multi-tier.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAE5F,qBAAa,qBAAsB,YAAW,YAAY;IACxD,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,KAAK,CAQX;gBAEU,OAAO,EAAE,qBAAqB;IAOpC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAgClD,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAatE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAWrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAatB,IAAI,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAYzC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC;IAYvB,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC;IAqBrC,OAAO,CAAC,aAAa;IAMrB,eAAe,IAAI,MAAM;IAInB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;CAajE"}