layercache 1.3.4 → 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-DKkrQ_Ky.d.cts → edge-D2FpRlyS.d.cts} +71 -22
- package/dist/{edge-DKkrQ_Ky.d.ts → edge-D2FpRlyS.d.ts} +71 -22
- 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 +399 -164
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +294 -81
- package/package.json +5 -5
- 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
|
*/
|
|
@@ -573,24 +614,24 @@ declare class CacheStack extends EventEmitter {
|
|
|
573
614
|
* and stores the result across all layers. Returns `null` if the key is not found
|
|
574
615
|
* and no `fetcher` is provided.
|
|
575
616
|
*/
|
|
576
|
-
get<T>(key: string, fetcher?:
|
|
617
|
+
get<T>(key: string, fetcher?: CacheFetcher<T>, options?: CacheGetOptions): Promise<T | null>;
|
|
577
618
|
/**
|
|
578
619
|
* Alias for `get(key, fetcher, options)` — explicit get-or-set pattern.
|
|
579
620
|
* Fetches and caches the value if not already present.
|
|
580
621
|
*/
|
|
581
|
-
getOrSet<T>(key: string, fetcher:
|
|
622
|
+
getOrSet<T>(key: string, fetcher: CacheFetcher<T>, options?: CacheGetOptions): Promise<T | null>;
|
|
582
623
|
/**
|
|
583
624
|
* Like `get()`, but throws `CacheMissError` instead of returning `null`.
|
|
584
625
|
* Useful when the value is expected to exist or the fetcher is expected to
|
|
585
626
|
* return non-null.
|
|
586
627
|
*/
|
|
587
|
-
getOrThrow<T>(key: string, fetcher?:
|
|
628
|
+
getOrThrow<T>(key: string, fetcher?: CacheFetcher<T>, options?: CacheGetOptions): Promise<T>;
|
|
588
629
|
/**
|
|
589
630
|
* Returns true if the given key exists and is not expired in any layer.
|
|
590
631
|
*/
|
|
591
632
|
has(key: string): Promise<boolean>;
|
|
592
633
|
/**
|
|
593
|
-
* Returns the remaining TTL in
|
|
634
|
+
* Returns the remaining TTL in milliseconds for the key in the fastest layer
|
|
594
635
|
* that has it, or null if the key is not found / has no TTL.
|
|
595
636
|
*/
|
|
596
637
|
ttl(key: string): Promise<number | null>;
|
|
@@ -621,9 +662,13 @@ declare class CacheStack extends EventEmitter {
|
|
|
621
662
|
*/
|
|
622
663
|
namespace(prefix: string): CacheNamespace;
|
|
623
664
|
invalidateByTag(tag: string): Promise<void>;
|
|
665
|
+
expireByTag(tag: string): Promise<void>;
|
|
624
666
|
invalidateByTags(tags: string[], mode?: 'any' | 'all'): Promise<void>;
|
|
667
|
+
expireByTags(tags: string[], mode?: 'any' | 'all'): Promise<void>;
|
|
625
668
|
invalidateByPattern(pattern: string): Promise<void>;
|
|
669
|
+
expireByPattern(pattern: string): Promise<void>;
|
|
626
670
|
invalidateByPrefix(prefix: string): Promise<void>;
|
|
671
|
+
expireByPrefix(prefix: string): Promise<void>;
|
|
627
672
|
getMetrics(): CacheMetricsSnapshot;
|
|
628
673
|
getStats(): CacheStatsSnapshot;
|
|
629
674
|
resetMetrics(): void;
|
|
@@ -653,8 +698,12 @@ declare class CacheStack extends EventEmitter {
|
|
|
653
698
|
private storeEntry;
|
|
654
699
|
private writeBatch;
|
|
655
700
|
private resolveFreshTtl;
|
|
656
|
-
private
|
|
701
|
+
private resolveLayerMs;
|
|
702
|
+
private resolveContextOptions;
|
|
703
|
+
private isPlainObject;
|
|
657
704
|
private deleteKeys;
|
|
705
|
+
private expireKeys;
|
|
706
|
+
private expireKeysInLayers;
|
|
658
707
|
private publishInvalidation;
|
|
659
708
|
private handleInvalidationMessage;
|
|
660
709
|
private getTagsForKey;
|
|
@@ -711,4 +760,4 @@ interface HonoCacheMiddlewareOptions extends CacheGetOptions {
|
|
|
711
760
|
}
|
|
712
761
|
declare function createHonoCacheMiddleware(cache: CacheStack, options?: HonoCacheMiddlewareOptions): (context: HonoLikeContext, next: () => Promise<void>) => Promise<unknown>;
|
|
713
762
|
|
|
714
|
-
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
|
*/
|
|
@@ -573,24 +614,24 @@ declare class CacheStack extends EventEmitter {
|
|
|
573
614
|
* and stores the result across all layers. Returns `null` if the key is not found
|
|
574
615
|
* and no `fetcher` is provided.
|
|
575
616
|
*/
|
|
576
|
-
get<T>(key: string, fetcher?:
|
|
617
|
+
get<T>(key: string, fetcher?: CacheFetcher<T>, options?: CacheGetOptions): Promise<T | null>;
|
|
577
618
|
/**
|
|
578
619
|
* Alias for `get(key, fetcher, options)` — explicit get-or-set pattern.
|
|
579
620
|
* Fetches and caches the value if not already present.
|
|
580
621
|
*/
|
|
581
|
-
getOrSet<T>(key: string, fetcher:
|
|
622
|
+
getOrSet<T>(key: string, fetcher: CacheFetcher<T>, options?: CacheGetOptions): Promise<T | null>;
|
|
582
623
|
/**
|
|
583
624
|
* Like `get()`, but throws `CacheMissError` instead of returning `null`.
|
|
584
625
|
* Useful when the value is expected to exist or the fetcher is expected to
|
|
585
626
|
* return non-null.
|
|
586
627
|
*/
|
|
587
|
-
getOrThrow<T>(key: string, fetcher?:
|
|
628
|
+
getOrThrow<T>(key: string, fetcher?: CacheFetcher<T>, options?: CacheGetOptions): Promise<T>;
|
|
588
629
|
/**
|
|
589
630
|
* Returns true if the given key exists and is not expired in any layer.
|
|
590
631
|
*/
|
|
591
632
|
has(key: string): Promise<boolean>;
|
|
592
633
|
/**
|
|
593
|
-
* Returns the remaining TTL in
|
|
634
|
+
* Returns the remaining TTL in milliseconds for the key in the fastest layer
|
|
594
635
|
* that has it, or null if the key is not found / has no TTL.
|
|
595
636
|
*/
|
|
596
637
|
ttl(key: string): Promise<number | null>;
|
|
@@ -621,9 +662,13 @@ declare class CacheStack extends EventEmitter {
|
|
|
621
662
|
*/
|
|
622
663
|
namespace(prefix: string): CacheNamespace;
|
|
623
664
|
invalidateByTag(tag: string): Promise<void>;
|
|
665
|
+
expireByTag(tag: string): Promise<void>;
|
|
624
666
|
invalidateByTags(tags: string[], mode?: 'any' | 'all'): Promise<void>;
|
|
667
|
+
expireByTags(tags: string[], mode?: 'any' | 'all'): Promise<void>;
|
|
625
668
|
invalidateByPattern(pattern: string): Promise<void>;
|
|
669
|
+
expireByPattern(pattern: string): Promise<void>;
|
|
626
670
|
invalidateByPrefix(prefix: string): Promise<void>;
|
|
671
|
+
expireByPrefix(prefix: string): Promise<void>;
|
|
627
672
|
getMetrics(): CacheMetricsSnapshot;
|
|
628
673
|
getStats(): CacheStatsSnapshot;
|
|
629
674
|
resetMetrics(): void;
|
|
@@ -653,8 +698,12 @@ declare class CacheStack extends EventEmitter {
|
|
|
653
698
|
private storeEntry;
|
|
654
699
|
private writeBatch;
|
|
655
700
|
private resolveFreshTtl;
|
|
656
|
-
private
|
|
701
|
+
private resolveLayerMs;
|
|
702
|
+
private resolveContextOptions;
|
|
703
|
+
private isPlainObject;
|
|
657
704
|
private deleteKeys;
|
|
705
|
+
private expireKeys;
|
|
706
|
+
private expireKeysInLayers;
|
|
658
707
|
private publishInvalidation;
|
|
659
708
|
private handleInvalidationMessage;
|
|
660
709
|
private getTagsForKey;
|
|
@@ -711,4 +760,4 @@ interface HonoCacheMiddlewareOptions extends CacheGetOptions {
|
|
|
711
760
|
}
|
|
712
761
|
declare function createHonoCacheMiddleware(cache: CacheStack, options?: HonoCacheMiddlewareOptions): (context: HonoLikeContext, next: () => Promise<void>) => Promise<unknown>;
|
|
713
762
|
|
|
714
|
-
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,
|