layercache 1.3.3 → 1.4.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/README.md +42 -41
- package/dist/{chunk-BORDQ3LA.js → chunk-7KMKQ6QZ.js} +15 -1
- package/dist/{chunk-5RCAX2BQ.js → chunk-FFZCC7EQ.js} +3 -3
- package/dist/{chunk-4PPBOOXT.js → chunk-KJDFYE5T.js} +38 -26
- package/dist/cli.cjs +9 -9
- package/dist/cli.js +4 -4
- package/dist/{edge-CUHTP9Bc.d.cts → edge-D2FpRlyS.d.cts} +74 -36
- package/dist/{edge-CUHTP9Bc.d.ts → edge-D2FpRlyS.d.ts} +74 -36
- package/dist/edge.cjs +9 -9
- package/dist/edge.d.cts +1 -1
- package/dist/edge.d.ts +1 -1
- package/dist/edge.js +2 -2
- package/dist/index.cjs +787 -466
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +682 -383
- package/package.json +6 -6
- package/benchmarks/direct.ts +0 -221
- package/benchmarks/edge-utils.ts +0 -28
- package/benchmarks/edge.ts +0 -491
- package/benchmarks/http.ts +0 -99
- package/benchmarks/latency.ts +0 -45
- package/benchmarks/memory-pressure.ts +0 -144
- package/benchmarks/multi-process-fanout.ts +0 -231
- package/benchmarks/multi-process-worker.ts +0 -151
- package/benchmarks/paths.ts +0 -25
- package/benchmarks/queue-amplification-utils.ts +0 -48
- package/benchmarks/queue-amplification.ts +0 -230
- package/benchmarks/redis-latency-proxy.ts +0 -100
- package/benchmarks/redis.ts +0 -107
- package/benchmarks/scenario-utils.ts +0 -38
- package/benchmarks/server.ts +0 -157
- package/benchmarks/slow-redis-latency.ts +0 -309
- package/benchmarks/slow-redis-utils.ts +0 -29
- package/benchmarks/slow-redis.ts +0 -47
- package/benchmarks/stampede.ts +0 -26
- package/benchmarks/stats.ts +0 -46
- package/benchmarks/workload.ts +0 -77
- package/examples/express-api/index.ts +0 -31
- package/examples/nextjs-api-routes/route.ts +0 -16
|
@@ -11,18 +11,26 @@ declare class CacheMissError extends Error {
|
|
|
11
11
|
interface LayerTtlMap {
|
|
12
12
|
[layerName: string]: number | undefined;
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
type CacheEntryWriteKind = 'value' | 'empty';
|
|
15
|
+
interface CacheEntryWriteOptions {
|
|
15
16
|
tags?: string[];
|
|
16
17
|
ttl?: number | LayerTtlMap;
|
|
17
18
|
ttlPolicy?: CacheTtlPolicy;
|
|
18
|
-
negativeCache?: boolean;
|
|
19
19
|
negativeTtl?: number | LayerTtlMap;
|
|
20
20
|
staleWhileRevalidate?: number | LayerTtlMap;
|
|
21
21
|
staleIfError?: number | LayerTtlMap;
|
|
22
22
|
ttlJitter?: number | LayerTtlMap;
|
|
23
|
+
adaptiveTtl?: boolean | CacheAdaptiveTtlOptions;
|
|
24
|
+
}
|
|
25
|
+
interface CacheContextOptionsContext {
|
|
26
|
+
key: string;
|
|
27
|
+
value: unknown;
|
|
28
|
+
kind: CacheEntryWriteKind;
|
|
29
|
+
}
|
|
30
|
+
interface CacheWriteOptions extends CacheEntryWriteOptions {
|
|
31
|
+
negativeCache?: boolean;
|
|
23
32
|
slidingTtl?: boolean;
|
|
24
33
|
refreshAhead?: number | LayerTtlMap;
|
|
25
|
-
adaptiveTtl?: boolean | CacheAdaptiveTtlOptions;
|
|
26
34
|
circuitBreaker?: CacheCircuitBreakerOptions;
|
|
27
35
|
fetcherRateLimit?: CacheRateLimitOptions;
|
|
28
36
|
/**
|
|
@@ -34,12 +42,37 @@ interface CacheWriteOptions {
|
|
|
34
42
|
* cache.get('key', fetchData, { shouldCache: (v) => v.status === 200 })
|
|
35
43
|
*/
|
|
36
44
|
shouldCache?: (value: unknown) => boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Optional resolver that can override cache entry options using the current
|
|
47
|
+
* write context. This runs right before a value is stored, so callers can
|
|
48
|
+
* derive TTLs or tags from the fetched value instead of guessing upfront.
|
|
49
|
+
*
|
|
50
|
+
* Returned values override any static entry options already present on the
|
|
51
|
+
* same object. Fetch controls like `shouldCache`, `negativeCache`,
|
|
52
|
+
* `refreshAhead`, or `circuitBreaker` are not affected.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* cache.get('oauth:token', fetchToken, {
|
|
56
|
+
* ttl: 300_000,
|
|
57
|
+
* contextOptions: ({ value }) => ({
|
|
58
|
+
* ttl: Math.max(1, Math.floor(((value as { refreshExpiresIn: number }).refreshExpiresIn ?? 0) / 1_000))
|
|
59
|
+
* })
|
|
60
|
+
* })
|
|
61
|
+
*/
|
|
62
|
+
contextOptions?: (context: CacheContextOptionsContext) => CacheEntryWriteOptions | undefined;
|
|
37
63
|
}
|
|
38
64
|
interface CacheGetOptions extends CacheWriteOptions {
|
|
39
65
|
}
|
|
66
|
+
interface CacheFetcherContext<T = unknown> {
|
|
67
|
+
key: string;
|
|
68
|
+
currentValue: T | undefined;
|
|
69
|
+
state: 'miss' | 'fresh' | 'stale-while-revalidate' | 'stale-if-error';
|
|
70
|
+
layer?: string;
|
|
71
|
+
}
|
|
72
|
+
type CacheFetcher<T = unknown> = (context: CacheFetcherContext<T>) => Promise<T>;
|
|
40
73
|
interface CacheMGetEntry<T> {
|
|
41
74
|
key: string;
|
|
42
|
-
fetch?:
|
|
75
|
+
fetch?: CacheFetcher<T>;
|
|
43
76
|
options?: CacheGetOptions;
|
|
44
77
|
}
|
|
45
78
|
interface CacheMSetEntry<T> {
|
|
@@ -75,7 +108,7 @@ interface CacheLayer {
|
|
|
75
108
|
*/
|
|
76
109
|
has?(key: string): Promise<boolean>;
|
|
77
110
|
/**
|
|
78
|
-
* Returns the remaining TTL in
|
|
111
|
+
* Returns the remaining TTL in milliseconds for the key, or null if the key
|
|
79
112
|
* does not exist, has no TTL, or has already expired.
|
|
80
113
|
* Implementations may omit this.
|
|
81
114
|
*/
|
|
@@ -159,7 +192,7 @@ interface InvalidationMessage {
|
|
|
159
192
|
scope: 'key' | 'keys' | 'clear';
|
|
160
193
|
sourceId: string;
|
|
161
194
|
keys?: string[];
|
|
162
|
-
operation?: 'write' | 'delete' | 'invalidate' | 'clear';
|
|
195
|
+
operation?: 'write' | 'delete' | 'invalidate' | 'expire' | 'clear';
|
|
163
196
|
}
|
|
164
197
|
interface InvalidationBus {
|
|
165
198
|
subscribe(handler: (message: InvalidationMessage) => Promise<void> | void): Promise<() => Promise<void> | void>;
|
|
@@ -255,7 +288,7 @@ interface CacheWriteBehindOptions {
|
|
|
255
288
|
}
|
|
256
289
|
interface CacheWarmEntry<T = unknown> {
|
|
257
290
|
key: string;
|
|
258
|
-
fetcher:
|
|
291
|
+
fetcher: CacheFetcher<T>;
|
|
259
292
|
options?: CacheGetOptions;
|
|
260
293
|
priority?: number;
|
|
261
294
|
}
|
|
@@ -301,12 +334,12 @@ interface CacheInspectResult {
|
|
|
301
334
|
key: string;
|
|
302
335
|
/** Layers in which the key is currently stored (not expired). */
|
|
303
336
|
foundInLayers: string[];
|
|
304
|
-
/** Remaining fresh TTL in
|
|
305
|
-
|
|
306
|
-
/** Remaining stale-while-revalidate window in
|
|
307
|
-
|
|
308
|
-
/** Remaining stale-if-error window in
|
|
309
|
-
|
|
337
|
+
/** Remaining fresh TTL in milliseconds, or null if no expiry or not an envelope. */
|
|
338
|
+
freshTtlMs: number | null;
|
|
339
|
+
/** Remaining stale-while-revalidate window in milliseconds, or null. */
|
|
340
|
+
staleTtlMs: number | null;
|
|
341
|
+
/** Remaining stale-if-error window in milliseconds, or null. */
|
|
342
|
+
errorTtlMs: number | null;
|
|
310
343
|
/** Whether the key is currently serving stale-while-revalidate. */
|
|
311
344
|
isStale: boolean;
|
|
312
345
|
/** Tags associated with this key (from the TagIndex). */
|
|
@@ -335,6 +368,10 @@ interface CacheStackEvents {
|
|
|
335
368
|
delete: {
|
|
336
369
|
keys: string[];
|
|
337
370
|
};
|
|
371
|
+
/** Fired after one or more keys are marked expired but retained. */
|
|
372
|
+
expire: {
|
|
373
|
+
keys: string[];
|
|
374
|
+
};
|
|
338
375
|
/** Fired when a value is backfilled into a faster layer. */
|
|
339
376
|
backfill: {
|
|
340
377
|
key: string;
|
|
@@ -486,12 +523,12 @@ declare class CacheNamespace {
|
|
|
486
523
|
private static readonly metricsMutexes;
|
|
487
524
|
private metrics;
|
|
488
525
|
constructor(cache: CacheStack, prefix: string);
|
|
489
|
-
get<T>(key: string, fetcher?:
|
|
490
|
-
getOrSet<T>(key: string, fetcher:
|
|
526
|
+
get<T>(key: string, fetcher?: CacheFetcher<T>, options?: CacheGetOptions): Promise<T | null>;
|
|
527
|
+
getOrSet<T>(key: string, fetcher: CacheFetcher<T>, options?: CacheGetOptions): Promise<T | null>;
|
|
491
528
|
/**
|
|
492
529
|
* Like `get()`, but throws `CacheMissError` instead of returning `null`.
|
|
493
530
|
*/
|
|
494
|
-
getOrThrow<T>(key: string, fetcher?:
|
|
531
|
+
getOrThrow<T>(key: string, fetcher?: CacheFetcher<T>, options?: CacheGetOptions): Promise<T>;
|
|
495
532
|
has(key: string): Promise<boolean>;
|
|
496
533
|
ttl(key: string): Promise<number | null>;
|
|
497
534
|
set<T>(key: string, value: T, options?: CacheWriteOptions): Promise<void>;
|
|
@@ -501,9 +538,13 @@ declare class CacheNamespace {
|
|
|
501
538
|
mget<T>(entries: CacheMGetEntry<T>[]): Promise<Array<T | null>>;
|
|
502
539
|
mset<T>(entries: CacheMSetEntry<T>[]): Promise<void>;
|
|
503
540
|
invalidateByTag(tag: string): Promise<void>;
|
|
541
|
+
expireByTag(tag: string): Promise<void>;
|
|
504
542
|
invalidateByTags(tags: string[], mode?: 'any' | 'all'): Promise<void>;
|
|
543
|
+
expireByTags(tags: string[], mode?: 'any' | 'all'): Promise<void>;
|
|
505
544
|
invalidateByPattern(pattern: string): Promise<void>;
|
|
545
|
+
expireByPattern(pattern: string): Promise<void>;
|
|
506
546
|
invalidateByPrefix(prefix: string): Promise<void>;
|
|
547
|
+
expireByPrefix(prefix: string): Promise<void>;
|
|
507
548
|
/**
|
|
508
549
|
* Returns detailed metadata about a single cache key within this namespace.
|
|
509
550
|
*/
|
|
@@ -557,8 +598,6 @@ declare class CacheStack extends EventEmitter {
|
|
|
557
598
|
private readonly invalidation;
|
|
558
599
|
private readonly layerWriter;
|
|
559
600
|
private readonly snapshots;
|
|
560
|
-
private readonly backgroundRefreshes;
|
|
561
|
-
private readonly backgroundRefreshAbort;
|
|
562
601
|
private readonly layerDegradedUntil;
|
|
563
602
|
private readonly maintenance;
|
|
564
603
|
private readonly ttlResolver;
|
|
@@ -566,6 +605,7 @@ declare class CacheStack extends EventEmitter {
|
|
|
566
605
|
private nextOperationId;
|
|
567
606
|
private currentGeneration?;
|
|
568
607
|
private isDisconnecting;
|
|
608
|
+
private readonly reader;
|
|
569
609
|
private disconnectPromise?;
|
|
570
610
|
constructor(layers: CacheLayer[], options?: CacheStackOptions);
|
|
571
611
|
/**
|
|
@@ -574,25 +614,24 @@ declare class CacheStack extends EventEmitter {
|
|
|
574
614
|
* and stores the result across all layers. Returns `null` if the key is not found
|
|
575
615
|
* and no `fetcher` is provided.
|
|
576
616
|
*/
|
|
577
|
-
get<T>(key: string, fetcher?:
|
|
578
|
-
private getPrepared;
|
|
617
|
+
get<T>(key: string, fetcher?: CacheFetcher<T>, options?: CacheGetOptions): Promise<T | null>;
|
|
579
618
|
/**
|
|
580
619
|
* Alias for `get(key, fetcher, options)` — explicit get-or-set pattern.
|
|
581
620
|
* Fetches and caches the value if not already present.
|
|
582
621
|
*/
|
|
583
|
-
getOrSet<T>(key: string, fetcher:
|
|
622
|
+
getOrSet<T>(key: string, fetcher: CacheFetcher<T>, options?: CacheGetOptions): Promise<T | null>;
|
|
584
623
|
/**
|
|
585
624
|
* Like `get()`, but throws `CacheMissError` instead of returning `null`.
|
|
586
625
|
* Useful when the value is expected to exist or the fetcher is expected to
|
|
587
626
|
* return non-null.
|
|
588
627
|
*/
|
|
589
|
-
getOrThrow<T>(key: string, fetcher?:
|
|
628
|
+
getOrThrow<T>(key: string, fetcher?: CacheFetcher<T>, options?: CacheGetOptions): Promise<T>;
|
|
590
629
|
/**
|
|
591
630
|
* Returns true if the given key exists and is not expired in any layer.
|
|
592
631
|
*/
|
|
593
632
|
has(key: string): Promise<boolean>;
|
|
594
633
|
/**
|
|
595
|
-
* Returns the remaining TTL in
|
|
634
|
+
* Returns the remaining TTL in milliseconds for the key in the fastest layer
|
|
596
635
|
* that has it, or null if the key is not found / has no TTL.
|
|
597
636
|
*/
|
|
598
637
|
ttl(key: string): Promise<number | null>;
|
|
@@ -623,9 +662,13 @@ declare class CacheStack extends EventEmitter {
|
|
|
623
662
|
*/
|
|
624
663
|
namespace(prefix: string): CacheNamespace;
|
|
625
664
|
invalidateByTag(tag: string): Promise<void>;
|
|
665
|
+
expireByTag(tag: string): Promise<void>;
|
|
626
666
|
invalidateByTags(tags: string[], mode?: 'any' | 'all'): Promise<void>;
|
|
667
|
+
expireByTags(tags: string[], mode?: 'any' | 'all'): Promise<void>;
|
|
627
668
|
invalidateByPattern(pattern: string): Promise<void>;
|
|
669
|
+
expireByPattern(pattern: string): Promise<void>;
|
|
628
670
|
invalidateByPrefix(prefix: string): Promise<void>;
|
|
671
|
+
expireByPrefix(prefix: string): Promise<void>;
|
|
629
672
|
getMetrics(): CacheMetricsSnapshot;
|
|
630
673
|
getStats(): CacheStatsSnapshot;
|
|
631
674
|
resetMetrics(): void;
|
|
@@ -652,21 +695,15 @@ declare class CacheStack extends EventEmitter {
|
|
|
652
695
|
restoreFromFile(filePath: string): Promise<void>;
|
|
653
696
|
disconnect(): Promise<void>;
|
|
654
697
|
private initialize;
|
|
655
|
-
private fetchWithGuards;
|
|
656
|
-
private waitForFreshValue;
|
|
657
|
-
private fetchAndPopulate;
|
|
658
698
|
private storeEntry;
|
|
659
699
|
private writeBatch;
|
|
660
|
-
private readFromLayers;
|
|
661
|
-
private readLayerEntry;
|
|
662
|
-
private backfill;
|
|
663
700
|
private resolveFreshTtl;
|
|
664
|
-
private
|
|
665
|
-
private
|
|
666
|
-
private
|
|
667
|
-
private runBackgroundRefresh;
|
|
668
|
-
private resolveSingleFlightOptions;
|
|
701
|
+
private resolveLayerMs;
|
|
702
|
+
private resolveContextOptions;
|
|
703
|
+
private isPlainObject;
|
|
669
704
|
private deleteKeys;
|
|
705
|
+
private expireKeys;
|
|
706
|
+
private expireKeysInLayers;
|
|
670
707
|
private publishInvalidation;
|
|
671
708
|
private handleInvalidationMessage;
|
|
672
709
|
private getTagsForKey;
|
|
@@ -689,13 +726,14 @@ declare class CacheStack extends EventEmitter {
|
|
|
689
726
|
private validateWriteOptions;
|
|
690
727
|
private assertActive;
|
|
691
728
|
private awaitStartup;
|
|
729
|
+
private readLayerEntry;
|
|
730
|
+
private scheduleBackgroundRefresh;
|
|
692
731
|
private applyFreshReadPolicies;
|
|
693
732
|
private shouldSkipLayer;
|
|
694
733
|
private handleLayerFailure;
|
|
695
734
|
private reportRecoverableLayerFailure;
|
|
696
735
|
private isGracefulDegradationEnabled;
|
|
697
736
|
private recordCircuitFailure;
|
|
698
|
-
private isNegativeStoredValue;
|
|
699
737
|
private emitError;
|
|
700
738
|
private snapshotMaxBytes;
|
|
701
739
|
private snapshotMaxEntries;
|
|
@@ -722,4 +760,4 @@ interface HonoCacheMiddlewareOptions extends CacheGetOptions {
|
|
|
722
760
|
}
|
|
723
761
|
declare function createHonoCacheMiddleware(cache: CacheStack, options?: HonoCacheMiddlewareOptions): (context: HonoLikeContext, next: () => Promise<void>) => Promise<unknown>;
|
|
724
762
|
|
|
725
|
-
export {
|
|
763
|
+
export { CacheNamespace as A, type CacheRateLimitOptions as B, type CacheLogger as C, type CacheSnapshotEntry as D, type CacheStackEvents as E, type CacheStackOptions as F, type CacheStatsSnapshot as G, type CacheTtlPolicy as H, type InvalidationBus as I, type CacheTtlPolicyContext as J, type CacheWarmEntry as K, type CacheWarmOptions as L, type CacheWarmProgress as M, type CacheWriteBehindOptions as N, type CacheWriteOptions as O, type EvictionPolicy as P, type LayerTtlMap as Q, MemoryLayer as R, type MemoryLayerOptions as S, type MemoryLayerSnapshotEntry as T, PatternMatcher as U, TagIndex as V, createHonoCacheMiddleware as W, type InvalidationMessage as a, type CacheTagIndex as b, CacheStack as c, type CacheWrapOptions as d, type CacheGetOptions as e, type CacheLayer as f, type CacheSerializer as g, type CacheLayerSetManyEntry as h, type CacheSingleFlightCoordinator as i, type CacheSingleFlightExecutionOptions as j, type CacheAdaptiveTtlOptions as k, type CacheCircuitBreakerOptions as l, type CacheContextOptionsContext as m, type CacheDegradationOptions as n, type CacheEntryWriteKind as o, type CacheEntryWriteOptions as p, type CacheFetcher as q, type CacheFetcherContext as r, type CacheHealthCheckResult as s, type CacheHitRateSnapshot as t, type CacheInspectResult as u, type CacheLayerLatency as v, type CacheMGetEntry as w, type CacheMSetEntry as x, type CacheMetricsSnapshot as y, CacheMissError as z };
|
|
@@ -11,18 +11,26 @@ declare class CacheMissError extends Error {
|
|
|
11
11
|
interface LayerTtlMap {
|
|
12
12
|
[layerName: string]: number | undefined;
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
type CacheEntryWriteKind = 'value' | 'empty';
|
|
15
|
+
interface CacheEntryWriteOptions {
|
|
15
16
|
tags?: string[];
|
|
16
17
|
ttl?: number | LayerTtlMap;
|
|
17
18
|
ttlPolicy?: CacheTtlPolicy;
|
|
18
|
-
negativeCache?: boolean;
|
|
19
19
|
negativeTtl?: number | LayerTtlMap;
|
|
20
20
|
staleWhileRevalidate?: number | LayerTtlMap;
|
|
21
21
|
staleIfError?: number | LayerTtlMap;
|
|
22
22
|
ttlJitter?: number | LayerTtlMap;
|
|
23
|
+
adaptiveTtl?: boolean | CacheAdaptiveTtlOptions;
|
|
24
|
+
}
|
|
25
|
+
interface CacheContextOptionsContext {
|
|
26
|
+
key: string;
|
|
27
|
+
value: unknown;
|
|
28
|
+
kind: CacheEntryWriteKind;
|
|
29
|
+
}
|
|
30
|
+
interface CacheWriteOptions extends CacheEntryWriteOptions {
|
|
31
|
+
negativeCache?: boolean;
|
|
23
32
|
slidingTtl?: boolean;
|
|
24
33
|
refreshAhead?: number | LayerTtlMap;
|
|
25
|
-
adaptiveTtl?: boolean | CacheAdaptiveTtlOptions;
|
|
26
34
|
circuitBreaker?: CacheCircuitBreakerOptions;
|
|
27
35
|
fetcherRateLimit?: CacheRateLimitOptions;
|
|
28
36
|
/**
|
|
@@ -34,12 +42,37 @@ interface CacheWriteOptions {
|
|
|
34
42
|
* cache.get('key', fetchData, { shouldCache: (v) => v.status === 200 })
|
|
35
43
|
*/
|
|
36
44
|
shouldCache?: (value: unknown) => boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Optional resolver that can override cache entry options using the current
|
|
47
|
+
* write context. This runs right before a value is stored, so callers can
|
|
48
|
+
* derive TTLs or tags from the fetched value instead of guessing upfront.
|
|
49
|
+
*
|
|
50
|
+
* Returned values override any static entry options already present on the
|
|
51
|
+
* same object. Fetch controls like `shouldCache`, `negativeCache`,
|
|
52
|
+
* `refreshAhead`, or `circuitBreaker` are not affected.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* cache.get('oauth:token', fetchToken, {
|
|
56
|
+
* ttl: 300_000,
|
|
57
|
+
* contextOptions: ({ value }) => ({
|
|
58
|
+
* ttl: Math.max(1, Math.floor(((value as { refreshExpiresIn: number }).refreshExpiresIn ?? 0) / 1_000))
|
|
59
|
+
* })
|
|
60
|
+
* })
|
|
61
|
+
*/
|
|
62
|
+
contextOptions?: (context: CacheContextOptionsContext) => CacheEntryWriteOptions | undefined;
|
|
37
63
|
}
|
|
38
64
|
interface CacheGetOptions extends CacheWriteOptions {
|
|
39
65
|
}
|
|
66
|
+
interface CacheFetcherContext<T = unknown> {
|
|
67
|
+
key: string;
|
|
68
|
+
currentValue: T | undefined;
|
|
69
|
+
state: 'miss' | 'fresh' | 'stale-while-revalidate' | 'stale-if-error';
|
|
70
|
+
layer?: string;
|
|
71
|
+
}
|
|
72
|
+
type CacheFetcher<T = unknown> = (context: CacheFetcherContext<T>) => Promise<T>;
|
|
40
73
|
interface CacheMGetEntry<T> {
|
|
41
74
|
key: string;
|
|
42
|
-
fetch?:
|
|
75
|
+
fetch?: CacheFetcher<T>;
|
|
43
76
|
options?: CacheGetOptions;
|
|
44
77
|
}
|
|
45
78
|
interface CacheMSetEntry<T> {
|
|
@@ -75,7 +108,7 @@ interface CacheLayer {
|
|
|
75
108
|
*/
|
|
76
109
|
has?(key: string): Promise<boolean>;
|
|
77
110
|
/**
|
|
78
|
-
* Returns the remaining TTL in
|
|
111
|
+
* Returns the remaining TTL in milliseconds for the key, or null if the key
|
|
79
112
|
* does not exist, has no TTL, or has already expired.
|
|
80
113
|
* Implementations may omit this.
|
|
81
114
|
*/
|
|
@@ -159,7 +192,7 @@ interface InvalidationMessage {
|
|
|
159
192
|
scope: 'key' | 'keys' | 'clear';
|
|
160
193
|
sourceId: string;
|
|
161
194
|
keys?: string[];
|
|
162
|
-
operation?: 'write' | 'delete' | 'invalidate' | 'clear';
|
|
195
|
+
operation?: 'write' | 'delete' | 'invalidate' | 'expire' | 'clear';
|
|
163
196
|
}
|
|
164
197
|
interface InvalidationBus {
|
|
165
198
|
subscribe(handler: (message: InvalidationMessage) => Promise<void> | void): Promise<() => Promise<void> | void>;
|
|
@@ -255,7 +288,7 @@ interface CacheWriteBehindOptions {
|
|
|
255
288
|
}
|
|
256
289
|
interface CacheWarmEntry<T = unknown> {
|
|
257
290
|
key: string;
|
|
258
|
-
fetcher:
|
|
291
|
+
fetcher: CacheFetcher<T>;
|
|
259
292
|
options?: CacheGetOptions;
|
|
260
293
|
priority?: number;
|
|
261
294
|
}
|
|
@@ -301,12 +334,12 @@ interface CacheInspectResult {
|
|
|
301
334
|
key: string;
|
|
302
335
|
/** Layers in which the key is currently stored (not expired). */
|
|
303
336
|
foundInLayers: string[];
|
|
304
|
-
/** Remaining fresh TTL in
|
|
305
|
-
|
|
306
|
-
/** Remaining stale-while-revalidate window in
|
|
307
|
-
|
|
308
|
-
/** Remaining stale-if-error window in
|
|
309
|
-
|
|
337
|
+
/** Remaining fresh TTL in milliseconds, or null if no expiry or not an envelope. */
|
|
338
|
+
freshTtlMs: number | null;
|
|
339
|
+
/** Remaining stale-while-revalidate window in milliseconds, or null. */
|
|
340
|
+
staleTtlMs: number | null;
|
|
341
|
+
/** Remaining stale-if-error window in milliseconds, or null. */
|
|
342
|
+
errorTtlMs: number | null;
|
|
310
343
|
/** Whether the key is currently serving stale-while-revalidate. */
|
|
311
344
|
isStale: boolean;
|
|
312
345
|
/** Tags associated with this key (from the TagIndex). */
|
|
@@ -335,6 +368,10 @@ interface CacheStackEvents {
|
|
|
335
368
|
delete: {
|
|
336
369
|
keys: string[];
|
|
337
370
|
};
|
|
371
|
+
/** Fired after one or more keys are marked expired but retained. */
|
|
372
|
+
expire: {
|
|
373
|
+
keys: string[];
|
|
374
|
+
};
|
|
338
375
|
/** Fired when a value is backfilled into a faster layer. */
|
|
339
376
|
backfill: {
|
|
340
377
|
key: string;
|
|
@@ -486,12 +523,12 @@ declare class CacheNamespace {
|
|
|
486
523
|
private static readonly metricsMutexes;
|
|
487
524
|
private metrics;
|
|
488
525
|
constructor(cache: CacheStack, prefix: string);
|
|
489
|
-
get<T>(key: string, fetcher?:
|
|
490
|
-
getOrSet<T>(key: string, fetcher:
|
|
526
|
+
get<T>(key: string, fetcher?: CacheFetcher<T>, options?: CacheGetOptions): Promise<T | null>;
|
|
527
|
+
getOrSet<T>(key: string, fetcher: CacheFetcher<T>, options?: CacheGetOptions): Promise<T | null>;
|
|
491
528
|
/**
|
|
492
529
|
* Like `get()`, but throws `CacheMissError` instead of returning `null`.
|
|
493
530
|
*/
|
|
494
|
-
getOrThrow<T>(key: string, fetcher?:
|
|
531
|
+
getOrThrow<T>(key: string, fetcher?: CacheFetcher<T>, options?: CacheGetOptions): Promise<T>;
|
|
495
532
|
has(key: string): Promise<boolean>;
|
|
496
533
|
ttl(key: string): Promise<number | null>;
|
|
497
534
|
set<T>(key: string, value: T, options?: CacheWriteOptions): Promise<void>;
|
|
@@ -501,9 +538,13 @@ declare class CacheNamespace {
|
|
|
501
538
|
mget<T>(entries: CacheMGetEntry<T>[]): Promise<Array<T | null>>;
|
|
502
539
|
mset<T>(entries: CacheMSetEntry<T>[]): Promise<void>;
|
|
503
540
|
invalidateByTag(tag: string): Promise<void>;
|
|
541
|
+
expireByTag(tag: string): Promise<void>;
|
|
504
542
|
invalidateByTags(tags: string[], mode?: 'any' | 'all'): Promise<void>;
|
|
543
|
+
expireByTags(tags: string[], mode?: 'any' | 'all'): Promise<void>;
|
|
505
544
|
invalidateByPattern(pattern: string): Promise<void>;
|
|
545
|
+
expireByPattern(pattern: string): Promise<void>;
|
|
506
546
|
invalidateByPrefix(prefix: string): Promise<void>;
|
|
547
|
+
expireByPrefix(prefix: string): Promise<void>;
|
|
507
548
|
/**
|
|
508
549
|
* Returns detailed metadata about a single cache key within this namespace.
|
|
509
550
|
*/
|
|
@@ -557,8 +598,6 @@ declare class CacheStack extends EventEmitter {
|
|
|
557
598
|
private readonly invalidation;
|
|
558
599
|
private readonly layerWriter;
|
|
559
600
|
private readonly snapshots;
|
|
560
|
-
private readonly backgroundRefreshes;
|
|
561
|
-
private readonly backgroundRefreshAbort;
|
|
562
601
|
private readonly layerDegradedUntil;
|
|
563
602
|
private readonly maintenance;
|
|
564
603
|
private readonly ttlResolver;
|
|
@@ -566,6 +605,7 @@ declare class CacheStack extends EventEmitter {
|
|
|
566
605
|
private nextOperationId;
|
|
567
606
|
private currentGeneration?;
|
|
568
607
|
private isDisconnecting;
|
|
608
|
+
private readonly reader;
|
|
569
609
|
private disconnectPromise?;
|
|
570
610
|
constructor(layers: CacheLayer[], options?: CacheStackOptions);
|
|
571
611
|
/**
|
|
@@ -574,25 +614,24 @@ declare class CacheStack extends EventEmitter {
|
|
|
574
614
|
* and stores the result across all layers. Returns `null` if the key is not found
|
|
575
615
|
* and no `fetcher` is provided.
|
|
576
616
|
*/
|
|
577
|
-
get<T>(key: string, fetcher?:
|
|
578
|
-
private getPrepared;
|
|
617
|
+
get<T>(key: string, fetcher?: CacheFetcher<T>, options?: CacheGetOptions): Promise<T | null>;
|
|
579
618
|
/**
|
|
580
619
|
* Alias for `get(key, fetcher, options)` — explicit get-or-set pattern.
|
|
581
620
|
* Fetches and caches the value if not already present.
|
|
582
621
|
*/
|
|
583
|
-
getOrSet<T>(key: string, fetcher:
|
|
622
|
+
getOrSet<T>(key: string, fetcher: CacheFetcher<T>, options?: CacheGetOptions): Promise<T | null>;
|
|
584
623
|
/**
|
|
585
624
|
* Like `get()`, but throws `CacheMissError` instead of returning `null`.
|
|
586
625
|
* Useful when the value is expected to exist or the fetcher is expected to
|
|
587
626
|
* return non-null.
|
|
588
627
|
*/
|
|
589
|
-
getOrThrow<T>(key: string, fetcher?:
|
|
628
|
+
getOrThrow<T>(key: string, fetcher?: CacheFetcher<T>, options?: CacheGetOptions): Promise<T>;
|
|
590
629
|
/**
|
|
591
630
|
* Returns true if the given key exists and is not expired in any layer.
|
|
592
631
|
*/
|
|
593
632
|
has(key: string): Promise<boolean>;
|
|
594
633
|
/**
|
|
595
|
-
* Returns the remaining TTL in
|
|
634
|
+
* Returns the remaining TTL in milliseconds for the key in the fastest layer
|
|
596
635
|
* that has it, or null if the key is not found / has no TTL.
|
|
597
636
|
*/
|
|
598
637
|
ttl(key: string): Promise<number | null>;
|
|
@@ -623,9 +662,13 @@ declare class CacheStack extends EventEmitter {
|
|
|
623
662
|
*/
|
|
624
663
|
namespace(prefix: string): CacheNamespace;
|
|
625
664
|
invalidateByTag(tag: string): Promise<void>;
|
|
665
|
+
expireByTag(tag: string): Promise<void>;
|
|
626
666
|
invalidateByTags(tags: string[], mode?: 'any' | 'all'): Promise<void>;
|
|
667
|
+
expireByTags(tags: string[], mode?: 'any' | 'all'): Promise<void>;
|
|
627
668
|
invalidateByPattern(pattern: string): Promise<void>;
|
|
669
|
+
expireByPattern(pattern: string): Promise<void>;
|
|
628
670
|
invalidateByPrefix(prefix: string): Promise<void>;
|
|
671
|
+
expireByPrefix(prefix: string): Promise<void>;
|
|
629
672
|
getMetrics(): CacheMetricsSnapshot;
|
|
630
673
|
getStats(): CacheStatsSnapshot;
|
|
631
674
|
resetMetrics(): void;
|
|
@@ -652,21 +695,15 @@ declare class CacheStack extends EventEmitter {
|
|
|
652
695
|
restoreFromFile(filePath: string): Promise<void>;
|
|
653
696
|
disconnect(): Promise<void>;
|
|
654
697
|
private initialize;
|
|
655
|
-
private fetchWithGuards;
|
|
656
|
-
private waitForFreshValue;
|
|
657
|
-
private fetchAndPopulate;
|
|
658
698
|
private storeEntry;
|
|
659
699
|
private writeBatch;
|
|
660
|
-
private readFromLayers;
|
|
661
|
-
private readLayerEntry;
|
|
662
|
-
private backfill;
|
|
663
700
|
private resolveFreshTtl;
|
|
664
|
-
private
|
|
665
|
-
private
|
|
666
|
-
private
|
|
667
|
-
private runBackgroundRefresh;
|
|
668
|
-
private resolveSingleFlightOptions;
|
|
701
|
+
private resolveLayerMs;
|
|
702
|
+
private resolveContextOptions;
|
|
703
|
+
private isPlainObject;
|
|
669
704
|
private deleteKeys;
|
|
705
|
+
private expireKeys;
|
|
706
|
+
private expireKeysInLayers;
|
|
670
707
|
private publishInvalidation;
|
|
671
708
|
private handleInvalidationMessage;
|
|
672
709
|
private getTagsForKey;
|
|
@@ -689,13 +726,14 @@ declare class CacheStack extends EventEmitter {
|
|
|
689
726
|
private validateWriteOptions;
|
|
690
727
|
private assertActive;
|
|
691
728
|
private awaitStartup;
|
|
729
|
+
private readLayerEntry;
|
|
730
|
+
private scheduleBackgroundRefresh;
|
|
692
731
|
private applyFreshReadPolicies;
|
|
693
732
|
private shouldSkipLayer;
|
|
694
733
|
private handleLayerFailure;
|
|
695
734
|
private reportRecoverableLayerFailure;
|
|
696
735
|
private isGracefulDegradationEnabled;
|
|
697
736
|
private recordCircuitFailure;
|
|
698
|
-
private isNegativeStoredValue;
|
|
699
737
|
private emitError;
|
|
700
738
|
private snapshotMaxBytes;
|
|
701
739
|
private snapshotMaxEntries;
|
|
@@ -722,4 +760,4 @@ interface HonoCacheMiddlewareOptions extends CacheGetOptions {
|
|
|
722
760
|
}
|
|
723
761
|
declare function createHonoCacheMiddleware(cache: CacheStack, options?: HonoCacheMiddlewareOptions): (context: HonoLikeContext, next: () => Promise<void>) => Promise<unknown>;
|
|
724
762
|
|
|
725
|
-
export {
|
|
763
|
+
export { CacheNamespace as A, type CacheRateLimitOptions as B, type CacheLogger as C, type CacheSnapshotEntry as D, type CacheStackEvents as E, type CacheStackOptions as F, type CacheStatsSnapshot as G, type CacheTtlPolicy as H, type InvalidationBus as I, type CacheTtlPolicyContext as J, type CacheWarmEntry as K, type CacheWarmOptions as L, type CacheWarmProgress as M, type CacheWriteBehindOptions as N, type CacheWriteOptions as O, type EvictionPolicy as P, type LayerTtlMap as Q, MemoryLayer as R, type MemoryLayerOptions as S, type MemoryLayerSnapshotEntry as T, PatternMatcher as U, TagIndex as V, createHonoCacheMiddleware as W, type InvalidationMessage as a, type CacheTagIndex as b, CacheStack as c, type CacheWrapOptions as d, type CacheGetOptions as e, type CacheLayer as f, type CacheSerializer as g, type CacheLayerSetManyEntry as h, type CacheSingleFlightCoordinator as i, type CacheSingleFlightExecutionOptions as j, type CacheAdaptiveTtlOptions as k, type CacheCircuitBreakerOptions as l, type CacheContextOptionsContext as m, type CacheDegradationOptions as n, type CacheEntryWriteKind as o, type CacheEntryWriteOptions as p, type CacheFetcher as q, type CacheFetcherContext as r, type CacheHealthCheckResult as s, type CacheHitRateSnapshot as t, type CacheInspectResult as u, type CacheLayerLatency as v, type CacheMGetEntry as w, type CacheMSetEntry as x, type CacheMetricsSnapshot as y, CacheMissError as z };
|
package/dist/edge.cjs
CHANGED
|
@@ -67,17 +67,17 @@ function isStoredValueEnvelope(value) {
|
|
|
67
67
|
if (typeof v.freshUntil === "number" && typeof v.errorUntil === "number" && v.errorUntil < v.freshUntil) {
|
|
68
68
|
return false;
|
|
69
69
|
}
|
|
70
|
-
const
|
|
71
|
-
if (!
|
|
70
|
+
const maxTtlMs = 10 * 365 * 24 * 60 * 60 * 1e3;
|
|
71
|
+
if (!isValidEnvelopeTtlMs(v.freshTtlMs, maxTtlMs)) {
|
|
72
72
|
return false;
|
|
73
73
|
}
|
|
74
|
-
if (!
|
|
74
|
+
if (!isValidEnvelopeTtlMs(v.staleWhileRevalidateMs, maxTtlMs)) {
|
|
75
75
|
return false;
|
|
76
76
|
}
|
|
77
|
-
if (!
|
|
77
|
+
if (!isValidEnvelopeTtlMs(v.staleIfErrorMs, maxTtlMs)) {
|
|
78
78
|
return false;
|
|
79
79
|
}
|
|
80
|
-
if (v.
|
|
80
|
+
if (v.freshTtlMs == null && (v.staleWhileRevalidateMs != null || v.staleIfErrorMs != null)) {
|
|
81
81
|
return false;
|
|
82
82
|
}
|
|
83
83
|
return true;
|
|
@@ -91,11 +91,11 @@ function unwrapStoredValue(stored) {
|
|
|
91
91
|
}
|
|
92
92
|
return stored.value ?? null;
|
|
93
93
|
}
|
|
94
|
-
function
|
|
94
|
+
function isValidEnvelopeTtlMs(value, maxTtlMs) {
|
|
95
95
|
if (value == null) {
|
|
96
96
|
return true;
|
|
97
97
|
}
|
|
98
|
-
return typeof value === "number" && Number.isFinite(value) && value > 0 && value <=
|
|
98
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 && value <= maxTtlMs;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
// src/layers/MemoryLayer.ts
|
|
@@ -153,7 +153,7 @@ var MemoryLayer = class {
|
|
|
153
153
|
this.entries.delete(key);
|
|
154
154
|
this.entries.set(key, {
|
|
155
155
|
value,
|
|
156
|
-
expiresAt: ttl && ttl > 0 ? Date.now() + ttl
|
|
156
|
+
expiresAt: ttl && ttl > 0 ? Date.now() + ttl : null,
|
|
157
157
|
accessCount: 0,
|
|
158
158
|
insertedAt: Date.now()
|
|
159
159
|
});
|
|
@@ -184,7 +184,7 @@ var MemoryLayer = class {
|
|
|
184
184
|
if (entry.expiresAt === null) {
|
|
185
185
|
return null;
|
|
186
186
|
}
|
|
187
|
-
return Math.max(0, Math.ceil(
|
|
187
|
+
return Math.max(0, Math.ceil(entry.expiresAt - Date.now()));
|
|
188
188
|
}
|
|
189
189
|
async size() {
|
|
190
190
|
this.pruneExpired();
|
package/dist/edge.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry,
|
|
1
|
+
export { m as CacheContextOptionsContext, o as CacheEntryWriteKind, p as CacheEntryWriteOptions, e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry, y as CacheMetricsSnapshot, B as CacheRateLimitOptions, H as CacheTtlPolicy, J as CacheTtlPolicyContext, O as CacheWriteOptions, P as EvictionPolicy, R as MemoryLayer, S as MemoryLayerOptions, T as MemoryLayerSnapshotEntry, U as PatternMatcher, V as TagIndex, W as createHonoCacheMiddleware } from './edge-D2FpRlyS.cjs';
|
|
2
2
|
import 'node:events';
|
package/dist/edge.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry,
|
|
1
|
+
export { m as CacheContextOptionsContext, o as CacheEntryWriteKind, p as CacheEntryWriteOptions, e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry, y as CacheMetricsSnapshot, B as CacheRateLimitOptions, H as CacheTtlPolicy, J as CacheTtlPolicyContext, O as CacheWriteOptions, P as EvictionPolicy, R as MemoryLayer, S as MemoryLayerOptions, T as MemoryLayerSnapshotEntry, U as PatternMatcher, V as TagIndex, W as createHonoCacheMiddleware } from './edge-D2FpRlyS.js';
|
|
2
2
|
import 'node:events';
|
package/dist/edge.js
CHANGED
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
MemoryLayer,
|
|
3
3
|
TagIndex,
|
|
4
4
|
createHonoCacheMiddleware
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-FFZCC7EQ.js";
|
|
6
6
|
import {
|
|
7
7
|
PatternMatcher
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-KJDFYE5T.js";
|
|
9
9
|
export {
|
|
10
10
|
MemoryLayer,
|
|
11
11
|
PatternMatcher,
|