layercache 1.0.1 → 1.0.2

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.
@@ -1,3 +1,4 @@
1
+ import { EventEmitter } from 'node:events';
1
2
  import { DynamicModule } from '@nestjs/common';
2
3
 
3
4
  declare const CACHE_STACK: unique symbol;
@@ -5,6 +6,31 @@ declare const CACHE_STACK: unique symbol;
5
6
  interface LayerTtlMap {
6
7
  [layerName: string]: number | undefined;
7
8
  }
9
+ interface CacheWriteOptions {
10
+ tags?: string[];
11
+ ttl?: number | LayerTtlMap;
12
+ negativeCache?: boolean;
13
+ negativeTtl?: number | LayerTtlMap;
14
+ staleWhileRevalidate?: number | LayerTtlMap;
15
+ staleIfError?: number | LayerTtlMap;
16
+ ttlJitter?: number | LayerTtlMap;
17
+ slidingTtl?: boolean;
18
+ refreshAhead?: number | LayerTtlMap;
19
+ adaptiveTtl?: boolean | CacheAdaptiveTtlOptions;
20
+ circuitBreaker?: CacheCircuitBreakerOptions;
21
+ }
22
+ interface CacheGetOptions extends CacheWriteOptions {
23
+ }
24
+ interface CacheMGetEntry<T> {
25
+ key: string;
26
+ fetch?: () => Promise<T>;
27
+ options?: CacheGetOptions;
28
+ }
29
+ interface CacheMSetEntry<T> {
30
+ key: string;
31
+ value: T;
32
+ options?: CacheWriteOptions;
33
+ }
8
34
  interface CacheLayer {
9
35
  readonly name: string;
10
36
  readonly defaultTtl?: number;
@@ -18,8 +44,30 @@ interface CacheLayer {
18
44
  deleteMany?(keys: string[]): Promise<void>;
19
45
  keys?(): Promise<string[]>;
20
46
  }
47
+ interface CacheMetricsSnapshot {
48
+ hits: number;
49
+ misses: number;
50
+ fetches: number;
51
+ sets: number;
52
+ deletes: number;
53
+ backfills: number;
54
+ invalidations: number;
55
+ staleHits: number;
56
+ refreshes: number;
57
+ refreshErrors: number;
58
+ writeFailures: number;
59
+ singleFlightWaits: number;
60
+ negativeCacheHits: number;
61
+ circuitBreakerTrips: number;
62
+ degradedOperations: number;
63
+ hitsByLayer: Record<string, number>;
64
+ missesByLayer: Record<string, number>;
65
+ }
21
66
  interface CacheLogger {
22
- debug(message: string, context?: Record<string, unknown>): void;
67
+ debug?(message: string, context?: Record<string, unknown>): void;
68
+ info?(message: string, context?: Record<string, unknown>): void;
69
+ warn?(message: string, context?: Record<string, unknown>): void;
70
+ error?(message: string, context?: Record<string, unknown>): void;
23
71
  }
24
72
  interface CacheTagIndex {
25
73
  touch(key: string): Promise<void>;
@@ -53,18 +101,172 @@ interface CacheStackOptions {
53
101
  stampedePrevention?: boolean;
54
102
  invalidationBus?: InvalidationBus;
55
103
  tagIndex?: CacheTagIndex;
104
+ broadcastL1Invalidation?: boolean;
56
105
  publishSetInvalidation?: boolean;
57
106
  negativeCaching?: boolean;
58
107
  negativeTtl?: number | LayerTtlMap;
59
108
  staleWhileRevalidate?: number | LayerTtlMap;
60
109
  staleIfError?: number | LayerTtlMap;
61
110
  ttlJitter?: number | LayerTtlMap;
111
+ refreshAhead?: number | LayerTtlMap;
112
+ adaptiveTtl?: boolean | CacheAdaptiveTtlOptions;
113
+ circuitBreaker?: CacheCircuitBreakerOptions;
114
+ gracefulDegradation?: boolean | CacheDegradationOptions;
62
115
  writePolicy?: 'strict' | 'best-effort';
63
116
  singleFlightCoordinator?: CacheSingleFlightCoordinator;
64
117
  singleFlightLeaseMs?: number;
65
118
  singleFlightTimeoutMs?: number;
66
119
  singleFlightPollMs?: number;
67
120
  }
121
+ interface CacheAdaptiveTtlOptions {
122
+ hotAfter?: number;
123
+ step?: number | LayerTtlMap;
124
+ maxTtl?: number | LayerTtlMap;
125
+ }
126
+ interface CacheCircuitBreakerOptions {
127
+ failureThreshold?: number;
128
+ cooldownMs?: number;
129
+ }
130
+ interface CacheDegradationOptions {
131
+ retryAfterMs?: number;
132
+ }
133
+ interface CacheWarmEntry<T = unknown> {
134
+ key: string;
135
+ fetcher: () => Promise<T>;
136
+ options?: CacheGetOptions;
137
+ priority?: number;
138
+ }
139
+ interface CacheWarmOptions {
140
+ concurrency?: number;
141
+ continueOnError?: boolean;
142
+ }
143
+ interface CacheWrapOptions<TArgs extends unknown[] = unknown[]> extends CacheGetOptions {
144
+ keyResolver?: (...args: TArgs) => string;
145
+ }
146
+ interface CacheSnapshotEntry {
147
+ key: string;
148
+ value: unknown;
149
+ ttl?: number;
150
+ }
151
+ interface CacheStatsSnapshot {
152
+ metrics: CacheMetricsSnapshot;
153
+ layers: Array<{
154
+ name: string;
155
+ isLocal: boolean;
156
+ degradedUntil: number | null;
157
+ }>;
158
+ backgroundRefreshes: number;
159
+ }
160
+
161
+ declare class CacheNamespace {
162
+ private readonly cache;
163
+ private readonly prefix;
164
+ constructor(cache: CacheStack, prefix: string);
165
+ get<T>(key: string, fetcher?: () => Promise<T>, options?: CacheGetOptions): Promise<T | null>;
166
+ set<T>(key: string, value: T, options?: CacheWriteOptions): Promise<void>;
167
+ delete(key: string): Promise<void>;
168
+ clear(): Promise<void>;
169
+ mget<T>(entries: CacheMGetEntry<T>[]): Promise<Array<T | null>>;
170
+ mset<T>(entries: CacheMSetEntry<T>[]): Promise<void>;
171
+ invalidateByTag(tag: string): Promise<void>;
172
+ invalidateByPattern(pattern: string): Promise<void>;
173
+ wrap<TArgs extends unknown[], TResult>(keyPrefix: string, fetcher: (...args: TArgs) => Promise<TResult>, options?: CacheWrapOptions<TArgs>): (...args: TArgs) => Promise<TResult | null>;
174
+ warm(entries: CacheWarmEntry[], options?: CacheWarmOptions): Promise<void>;
175
+ getMetrics(): CacheMetricsSnapshot;
176
+ qualify(key: string): string;
177
+ }
178
+
179
+ declare class CacheStack extends EventEmitter {
180
+ private readonly layers;
181
+ private readonly options;
182
+ private readonly stampedeGuard;
183
+ private readonly metrics;
184
+ private readonly instanceId;
185
+ private readonly startup;
186
+ private unsubscribeInvalidation?;
187
+ private readonly logger;
188
+ private readonly tagIndex;
189
+ private readonly backgroundRefreshes;
190
+ private readonly accessProfiles;
191
+ private readonly layerDegradedUntil;
192
+ private readonly circuitBreakers;
193
+ private isDisconnecting;
194
+ private disconnectPromise?;
195
+ constructor(layers: CacheLayer[], options?: CacheStackOptions);
196
+ get<T>(key: string, fetcher?: () => Promise<T>, options?: CacheGetOptions): Promise<T | null>;
197
+ set<T>(key: string, value: T, options?: CacheWriteOptions): Promise<void>;
198
+ delete(key: string): Promise<void>;
199
+ clear(): Promise<void>;
200
+ mget<T>(entries: CacheMGetEntry<T>[]): Promise<Array<T | null>>;
201
+ mset<T>(entries: CacheMSetEntry<T>[]): Promise<void>;
202
+ warm(entries: CacheWarmEntry[], options?: CacheWarmOptions): Promise<void>;
203
+ wrap<TArgs extends unknown[], TResult>(prefix: string, fetcher: (...args: TArgs) => Promise<TResult>, options?: CacheWrapOptions<TArgs>): (...args: TArgs) => Promise<TResult | null>;
204
+ namespace(prefix: string): CacheNamespace;
205
+ invalidateByTag(tag: string): Promise<void>;
206
+ invalidateByPattern(pattern: string): Promise<void>;
207
+ getMetrics(): CacheMetricsSnapshot;
208
+ getStats(): CacheStatsSnapshot;
209
+ resetMetrics(): void;
210
+ exportState(): Promise<CacheSnapshotEntry[]>;
211
+ importState(entries: CacheSnapshotEntry[]): Promise<void>;
212
+ persistToFile(filePath: string): Promise<void>;
213
+ restoreFromFile(filePath: string): Promise<void>;
214
+ disconnect(): Promise<void>;
215
+ private initialize;
216
+ private fetchWithGuards;
217
+ private waitForFreshValue;
218
+ private fetchAndPopulate;
219
+ private storeEntry;
220
+ private readFromLayers;
221
+ private readLayerEntry;
222
+ private backfill;
223
+ private writeAcrossLayers;
224
+ private executeLayerOperations;
225
+ private resolveFreshTtl;
226
+ private resolveLayerSeconds;
227
+ private readLayerNumber;
228
+ private applyJitter;
229
+ private shouldNegativeCache;
230
+ private scheduleBackgroundRefresh;
231
+ private resolveSingleFlightOptions;
232
+ private deleteKeys;
233
+ private publishInvalidation;
234
+ private handleInvalidationMessage;
235
+ private formatError;
236
+ private sleep;
237
+ private shouldBroadcastL1Invalidation;
238
+ private deleteKeysFromLayers;
239
+ private validateConfiguration;
240
+ private validateWriteOptions;
241
+ private validateLayerNumberOption;
242
+ private validatePositiveNumber;
243
+ private validateNonNegativeNumber;
244
+ private validateCacheKey;
245
+ private serializeOptions;
246
+ private validateAdaptiveTtlOptions;
247
+ private validateCircuitBreakerOptions;
248
+ private applyFreshReadPolicies;
249
+ private applyAdaptiveTtl;
250
+ private recordAccess;
251
+ private incrementMetricMap;
252
+ private shouldSkipLayer;
253
+ private handleLayerFailure;
254
+ private isGracefulDegradationEnabled;
255
+ private assertCircuitClosed;
256
+ private recordCircuitFailure;
257
+ private resetCircuitBreaker;
258
+ private isNegativeStoredValue;
259
+ private emitError;
260
+ private serializeKeyPart;
261
+ private isCacheSnapshotEntries;
262
+ private normalizeForSerialization;
263
+ }
264
+
265
+ interface CacheableOptions<TArgs extends unknown[]> extends CacheWrapOptions<TArgs> {
266
+ cache: (instance: unknown) => CacheStack;
267
+ prefix?: string;
268
+ }
269
+ declare function Cacheable<TArgs extends unknown[] = unknown[]>(options: CacheableOptions<TArgs>): MethodDecorator;
68
270
 
69
271
  interface CacheStackModuleOptions {
70
272
  layers: CacheLayer[];
@@ -75,4 +277,4 @@ declare class CacheStackModule {
75
277
  static forRoot(options: CacheStackModuleOptions): DynamicModule;
76
278
  }
77
279
 
78
- export { CACHE_STACK, CacheStackModule, type CacheStackModuleOptions, InjectCacheStack };
280
+ export { CACHE_STACK, CacheStackModule, type CacheStackModuleOptions, Cacheable, InjectCacheStack };
@@ -1,3 +1,4 @@
1
+ import { EventEmitter } from 'node:events';
1
2
  import { DynamicModule } from '@nestjs/common';
2
3
 
3
4
  declare const CACHE_STACK: unique symbol;
@@ -5,6 +6,31 @@ declare const CACHE_STACK: unique symbol;
5
6
  interface LayerTtlMap {
6
7
  [layerName: string]: number | undefined;
7
8
  }
9
+ interface CacheWriteOptions {
10
+ tags?: string[];
11
+ ttl?: number | LayerTtlMap;
12
+ negativeCache?: boolean;
13
+ negativeTtl?: number | LayerTtlMap;
14
+ staleWhileRevalidate?: number | LayerTtlMap;
15
+ staleIfError?: number | LayerTtlMap;
16
+ ttlJitter?: number | LayerTtlMap;
17
+ slidingTtl?: boolean;
18
+ refreshAhead?: number | LayerTtlMap;
19
+ adaptiveTtl?: boolean | CacheAdaptiveTtlOptions;
20
+ circuitBreaker?: CacheCircuitBreakerOptions;
21
+ }
22
+ interface CacheGetOptions extends CacheWriteOptions {
23
+ }
24
+ interface CacheMGetEntry<T> {
25
+ key: string;
26
+ fetch?: () => Promise<T>;
27
+ options?: CacheGetOptions;
28
+ }
29
+ interface CacheMSetEntry<T> {
30
+ key: string;
31
+ value: T;
32
+ options?: CacheWriteOptions;
33
+ }
8
34
  interface CacheLayer {
9
35
  readonly name: string;
10
36
  readonly defaultTtl?: number;
@@ -18,8 +44,30 @@ interface CacheLayer {
18
44
  deleteMany?(keys: string[]): Promise<void>;
19
45
  keys?(): Promise<string[]>;
20
46
  }
47
+ interface CacheMetricsSnapshot {
48
+ hits: number;
49
+ misses: number;
50
+ fetches: number;
51
+ sets: number;
52
+ deletes: number;
53
+ backfills: number;
54
+ invalidations: number;
55
+ staleHits: number;
56
+ refreshes: number;
57
+ refreshErrors: number;
58
+ writeFailures: number;
59
+ singleFlightWaits: number;
60
+ negativeCacheHits: number;
61
+ circuitBreakerTrips: number;
62
+ degradedOperations: number;
63
+ hitsByLayer: Record<string, number>;
64
+ missesByLayer: Record<string, number>;
65
+ }
21
66
  interface CacheLogger {
22
- debug(message: string, context?: Record<string, unknown>): void;
67
+ debug?(message: string, context?: Record<string, unknown>): void;
68
+ info?(message: string, context?: Record<string, unknown>): void;
69
+ warn?(message: string, context?: Record<string, unknown>): void;
70
+ error?(message: string, context?: Record<string, unknown>): void;
23
71
  }
24
72
  interface CacheTagIndex {
25
73
  touch(key: string): Promise<void>;
@@ -53,18 +101,172 @@ interface CacheStackOptions {
53
101
  stampedePrevention?: boolean;
54
102
  invalidationBus?: InvalidationBus;
55
103
  tagIndex?: CacheTagIndex;
104
+ broadcastL1Invalidation?: boolean;
56
105
  publishSetInvalidation?: boolean;
57
106
  negativeCaching?: boolean;
58
107
  negativeTtl?: number | LayerTtlMap;
59
108
  staleWhileRevalidate?: number | LayerTtlMap;
60
109
  staleIfError?: number | LayerTtlMap;
61
110
  ttlJitter?: number | LayerTtlMap;
111
+ refreshAhead?: number | LayerTtlMap;
112
+ adaptiveTtl?: boolean | CacheAdaptiveTtlOptions;
113
+ circuitBreaker?: CacheCircuitBreakerOptions;
114
+ gracefulDegradation?: boolean | CacheDegradationOptions;
62
115
  writePolicy?: 'strict' | 'best-effort';
63
116
  singleFlightCoordinator?: CacheSingleFlightCoordinator;
64
117
  singleFlightLeaseMs?: number;
65
118
  singleFlightTimeoutMs?: number;
66
119
  singleFlightPollMs?: number;
67
120
  }
121
+ interface CacheAdaptiveTtlOptions {
122
+ hotAfter?: number;
123
+ step?: number | LayerTtlMap;
124
+ maxTtl?: number | LayerTtlMap;
125
+ }
126
+ interface CacheCircuitBreakerOptions {
127
+ failureThreshold?: number;
128
+ cooldownMs?: number;
129
+ }
130
+ interface CacheDegradationOptions {
131
+ retryAfterMs?: number;
132
+ }
133
+ interface CacheWarmEntry<T = unknown> {
134
+ key: string;
135
+ fetcher: () => Promise<T>;
136
+ options?: CacheGetOptions;
137
+ priority?: number;
138
+ }
139
+ interface CacheWarmOptions {
140
+ concurrency?: number;
141
+ continueOnError?: boolean;
142
+ }
143
+ interface CacheWrapOptions<TArgs extends unknown[] = unknown[]> extends CacheGetOptions {
144
+ keyResolver?: (...args: TArgs) => string;
145
+ }
146
+ interface CacheSnapshotEntry {
147
+ key: string;
148
+ value: unknown;
149
+ ttl?: number;
150
+ }
151
+ interface CacheStatsSnapshot {
152
+ metrics: CacheMetricsSnapshot;
153
+ layers: Array<{
154
+ name: string;
155
+ isLocal: boolean;
156
+ degradedUntil: number | null;
157
+ }>;
158
+ backgroundRefreshes: number;
159
+ }
160
+
161
+ declare class CacheNamespace {
162
+ private readonly cache;
163
+ private readonly prefix;
164
+ constructor(cache: CacheStack, prefix: string);
165
+ get<T>(key: string, fetcher?: () => Promise<T>, options?: CacheGetOptions): Promise<T | null>;
166
+ set<T>(key: string, value: T, options?: CacheWriteOptions): Promise<void>;
167
+ delete(key: string): Promise<void>;
168
+ clear(): Promise<void>;
169
+ mget<T>(entries: CacheMGetEntry<T>[]): Promise<Array<T | null>>;
170
+ mset<T>(entries: CacheMSetEntry<T>[]): Promise<void>;
171
+ invalidateByTag(tag: string): Promise<void>;
172
+ invalidateByPattern(pattern: string): Promise<void>;
173
+ wrap<TArgs extends unknown[], TResult>(keyPrefix: string, fetcher: (...args: TArgs) => Promise<TResult>, options?: CacheWrapOptions<TArgs>): (...args: TArgs) => Promise<TResult | null>;
174
+ warm(entries: CacheWarmEntry[], options?: CacheWarmOptions): Promise<void>;
175
+ getMetrics(): CacheMetricsSnapshot;
176
+ qualify(key: string): string;
177
+ }
178
+
179
+ declare class CacheStack extends EventEmitter {
180
+ private readonly layers;
181
+ private readonly options;
182
+ private readonly stampedeGuard;
183
+ private readonly metrics;
184
+ private readonly instanceId;
185
+ private readonly startup;
186
+ private unsubscribeInvalidation?;
187
+ private readonly logger;
188
+ private readonly tagIndex;
189
+ private readonly backgroundRefreshes;
190
+ private readonly accessProfiles;
191
+ private readonly layerDegradedUntil;
192
+ private readonly circuitBreakers;
193
+ private isDisconnecting;
194
+ private disconnectPromise?;
195
+ constructor(layers: CacheLayer[], options?: CacheStackOptions);
196
+ get<T>(key: string, fetcher?: () => Promise<T>, options?: CacheGetOptions): Promise<T | null>;
197
+ set<T>(key: string, value: T, options?: CacheWriteOptions): Promise<void>;
198
+ delete(key: string): Promise<void>;
199
+ clear(): Promise<void>;
200
+ mget<T>(entries: CacheMGetEntry<T>[]): Promise<Array<T | null>>;
201
+ mset<T>(entries: CacheMSetEntry<T>[]): Promise<void>;
202
+ warm(entries: CacheWarmEntry[], options?: CacheWarmOptions): Promise<void>;
203
+ wrap<TArgs extends unknown[], TResult>(prefix: string, fetcher: (...args: TArgs) => Promise<TResult>, options?: CacheWrapOptions<TArgs>): (...args: TArgs) => Promise<TResult | null>;
204
+ namespace(prefix: string): CacheNamespace;
205
+ invalidateByTag(tag: string): Promise<void>;
206
+ invalidateByPattern(pattern: string): Promise<void>;
207
+ getMetrics(): CacheMetricsSnapshot;
208
+ getStats(): CacheStatsSnapshot;
209
+ resetMetrics(): void;
210
+ exportState(): Promise<CacheSnapshotEntry[]>;
211
+ importState(entries: CacheSnapshotEntry[]): Promise<void>;
212
+ persistToFile(filePath: string): Promise<void>;
213
+ restoreFromFile(filePath: string): Promise<void>;
214
+ disconnect(): Promise<void>;
215
+ private initialize;
216
+ private fetchWithGuards;
217
+ private waitForFreshValue;
218
+ private fetchAndPopulate;
219
+ private storeEntry;
220
+ private readFromLayers;
221
+ private readLayerEntry;
222
+ private backfill;
223
+ private writeAcrossLayers;
224
+ private executeLayerOperations;
225
+ private resolveFreshTtl;
226
+ private resolveLayerSeconds;
227
+ private readLayerNumber;
228
+ private applyJitter;
229
+ private shouldNegativeCache;
230
+ private scheduleBackgroundRefresh;
231
+ private resolveSingleFlightOptions;
232
+ private deleteKeys;
233
+ private publishInvalidation;
234
+ private handleInvalidationMessage;
235
+ private formatError;
236
+ private sleep;
237
+ private shouldBroadcastL1Invalidation;
238
+ private deleteKeysFromLayers;
239
+ private validateConfiguration;
240
+ private validateWriteOptions;
241
+ private validateLayerNumberOption;
242
+ private validatePositiveNumber;
243
+ private validateNonNegativeNumber;
244
+ private validateCacheKey;
245
+ private serializeOptions;
246
+ private validateAdaptiveTtlOptions;
247
+ private validateCircuitBreakerOptions;
248
+ private applyFreshReadPolicies;
249
+ private applyAdaptiveTtl;
250
+ private recordAccess;
251
+ private incrementMetricMap;
252
+ private shouldSkipLayer;
253
+ private handleLayerFailure;
254
+ private isGracefulDegradationEnabled;
255
+ private assertCircuitClosed;
256
+ private recordCircuitFailure;
257
+ private resetCircuitBreaker;
258
+ private isNegativeStoredValue;
259
+ private emitError;
260
+ private serializeKeyPart;
261
+ private isCacheSnapshotEntries;
262
+ private normalizeForSerialization;
263
+ }
264
+
265
+ interface CacheableOptions<TArgs extends unknown[]> extends CacheWrapOptions<TArgs> {
266
+ cache: (instance: unknown) => CacheStack;
267
+ prefix?: string;
268
+ }
269
+ declare function Cacheable<TArgs extends unknown[] = unknown[]>(options: CacheableOptions<TArgs>): MethodDecorator;
68
270
 
69
271
  interface CacheStackModuleOptions {
70
272
  layers: CacheLayer[];
@@ -75,4 +277,4 @@ declare class CacheStackModule {
75
277
  static forRoot(options: CacheStackModuleOptions): DynamicModule;
76
278
  }
77
279
 
78
- export { CACHE_STACK, CacheStackModule, type CacheStackModuleOptions, InjectCacheStack };
280
+ export { CACHE_STACK, CacheStackModule, type CacheStackModuleOptions, Cacheable, InjectCacheStack };