layercache 1.2.6 → 1.2.8
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 +4 -4
- package/dist/cli.cjs +12 -1
- package/dist/cli.js +12 -1
- package/dist/{edge-DLstcDMn.d.cts → edge-DBs8Ko5W.d.cts} +22 -23
- package/dist/{edge-DLstcDMn.d.ts → edge-DBs8Ko5W.d.ts} +22 -23
- package/dist/edge.d.cts +1 -1
- package/dist/edge.d.ts +1 -1
- package/dist/index.cjs +1325 -1112
- package/dist/index.d.cts +4 -5
- package/dist/index.d.ts +4 -5
- package/dist/index.js +1178 -965
- package/package.json +1 -1
- package/packages/nestjs/dist/index.cjs +1304 -1021
- package/packages/nestjs/dist/index.d.cts +22 -23
- package/packages/nestjs/dist/index.d.ts +22 -23
- package/packages/nestjs/dist/index.js +1303 -1020
package/README.md
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
<a href="./LICENSE"><img src="https://img.shields.io/badge/license-Apache_2.0-green" alt="license"></a>
|
|
16
16
|
<a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-first-3178C6?logo=typescript&logoColor=white" alt="TypeScript"></a>
|
|
17
17
|
<img src="https://img.shields.io/badge/Node.js-%E2%89%A5_20-339933?logo=nodedotjs&logoColor=white" alt="Node.js >= 20">
|
|
18
|
-
<img src="https://img.shields.io/badge/tests-
|
|
19
|
-
<a href="https://coveralls.io/github/flyingsquirrel0419/layercache?branch=main"><img src="https://coveralls.io/repos/github/flyingsquirrel0419/layercache/badge.svg?branch=main" alt="Coveralls"></a>
|
|
18
|
+
<img src="https://img.shields.io/badge/tests-397_passing-brightgreen" alt="tests">
|
|
19
|
+
<a href="https://coveralls.io/github/flyingsquirrel0419/layercache?branch=main"><img src="https://coveralls.io/repos/github/flyingsquirrel0419/layercache/badge.svg?branch=main&t=20260409" alt="Coveralls"></a>
|
|
20
20
|
</p>
|
|
21
21
|
|
|
22
22
|
<p align="center">
|
|
@@ -163,7 +163,7 @@ const cache = new CacheStack([
|
|
|
163
163
|
| **Per-layer latency** | Avg, max, and sample count using Welford's algorithm |
|
|
164
164
|
| **Health checks** | Async health endpoint per layer with latency measurement |
|
|
165
165
|
| **Event hooks** | `hit`, `miss`, `set`, `delete`, `stale-serve`, `stampede-dedupe`, `backfill`, `warm`, `error` |
|
|
166
|
-
| **OpenTelemetry** |
|
|
166
|
+
| **OpenTelemetry** | Hook-based distributed tracing support without method monkey-patching |
|
|
167
167
|
| **Prometheus exporter** | Metrics export including latency gauges |
|
|
168
168
|
| **HTTP stats handler** | JSON endpoint for dashboards |
|
|
169
169
|
| **Admin CLI** | `npx layercache stats\|keys\|invalidate` for Redis-backed caches |
|
|
@@ -183,7 +183,7 @@ layercache plugs into the frameworks you already use:
|
|
|
183
183
|
| **GraphQL** | `cacheGraphqlResolver(cache, prefix, resolver, opts)` - field resolver wrapper |
|
|
184
184
|
| **NestJS** | `@cachestack/nestjs` - `CacheStackModule.forRoot()`, `@Cacheable()` decorator |
|
|
185
185
|
| **Next.js** | Works natively with App Router and API routes |
|
|
186
|
-
| **OpenTelemetry** | `createOpenTelemetryPlugin(cache, tracer)` -
|
|
186
|
+
| **OpenTelemetry** | `createOpenTelemetryPlugin(cache, tracer)` - event-driven tracing spans without monkey-patching |
|
|
187
187
|
|
|
188
188
|
<details>
|
|
189
189
|
<summary><b>Express example</b></summary>
|
package/dist/cli.cjs
CHANGED
|
@@ -373,7 +373,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
373
373
|
try {
|
|
374
374
|
await redis.connect().catch((error) => {
|
|
375
375
|
const message = error instanceof Error ? error.message : String(error);
|
|
376
|
-
throw new Error(`Failed to connect to Redis: ${message}`);
|
|
376
|
+
throw new Error(`Failed to connect to Redis at ${maskRedisUrl(redisUrl)}: ${message}`);
|
|
377
377
|
});
|
|
378
378
|
if (args.command === "stats") {
|
|
379
379
|
const keys = await scanKeys(redis, args.pattern ?? "*");
|
|
@@ -528,6 +528,17 @@ function summarizeInspectableValue(value) {
|
|
|
528
528
|
}
|
|
529
529
|
return value;
|
|
530
530
|
}
|
|
531
|
+
function maskRedisUrl(url) {
|
|
532
|
+
try {
|
|
533
|
+
const parsed = new URL(url);
|
|
534
|
+
if (parsed.password) {
|
|
535
|
+
parsed.password = "***";
|
|
536
|
+
}
|
|
537
|
+
return parsed.toString();
|
|
538
|
+
} catch {
|
|
539
|
+
return url.replace(/:([^@/]+)@/, ":***@");
|
|
540
|
+
}
|
|
541
|
+
}
|
|
531
542
|
if (process.argv[1]?.includes("cli.")) {
|
|
532
543
|
void main();
|
|
533
544
|
}
|
package/dist/cli.js
CHANGED
|
@@ -31,7 +31,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
31
31
|
try {
|
|
32
32
|
await redis.connect().catch((error) => {
|
|
33
33
|
const message = error instanceof Error ? error.message : String(error);
|
|
34
|
-
throw new Error(`Failed to connect to Redis: ${message}`);
|
|
34
|
+
throw new Error(`Failed to connect to Redis at ${maskRedisUrl(redisUrl)}: ${message}`);
|
|
35
35
|
});
|
|
36
36
|
if (args.command === "stats") {
|
|
37
37
|
const keys = await scanKeys(redis, args.pattern ?? "*");
|
|
@@ -186,6 +186,17 @@ function summarizeInspectableValue(value) {
|
|
|
186
186
|
}
|
|
187
187
|
return value;
|
|
188
188
|
}
|
|
189
|
+
function maskRedisUrl(url) {
|
|
190
|
+
try {
|
|
191
|
+
const parsed = new URL(url);
|
|
192
|
+
if (parsed.password) {
|
|
193
|
+
parsed.password = "***";
|
|
194
|
+
}
|
|
195
|
+
return parsed.toString();
|
|
196
|
+
} catch {
|
|
197
|
+
return url.replace(/:([^@/]+)@/, ":***@");
|
|
198
|
+
}
|
|
199
|
+
}
|
|
189
200
|
if (process.argv[1]?.includes("cli.")) {
|
|
190
201
|
void main();
|
|
191
202
|
}
|
|
@@ -352,6 +352,21 @@ interface CacheStackEvents {
|
|
|
352
352
|
warm: {
|
|
353
353
|
key: string;
|
|
354
354
|
};
|
|
355
|
+
/** Fired immediately before a high-level cache operation begins. */
|
|
356
|
+
'operation-start': {
|
|
357
|
+
id: number;
|
|
358
|
+
name: string;
|
|
359
|
+
attributes?: Record<string, unknown>;
|
|
360
|
+
};
|
|
361
|
+
/** Fired after a high-level cache operation finishes. */
|
|
362
|
+
'operation-end': {
|
|
363
|
+
id: number;
|
|
364
|
+
name: string;
|
|
365
|
+
attributes?: Record<string, unknown>;
|
|
366
|
+
success: boolean;
|
|
367
|
+
result?: 'null';
|
|
368
|
+
error?: unknown;
|
|
369
|
+
};
|
|
355
370
|
/** Fired when an error occurs (layer failure, circuit breaker, etc.). */
|
|
356
371
|
error: {
|
|
357
372
|
operation: string;
|
|
@@ -537,17 +552,16 @@ declare class CacheStack extends EventEmitter {
|
|
|
537
552
|
private readonly keyDiscovery;
|
|
538
553
|
private readonly fetchRateLimiter;
|
|
539
554
|
private readonly snapshotSerializer;
|
|
555
|
+
private readonly invalidation;
|
|
556
|
+
private readonly layerWriter;
|
|
557
|
+
private readonly snapshots;
|
|
540
558
|
private readonly backgroundRefreshes;
|
|
541
559
|
private readonly layerDegradedUntil;
|
|
542
|
-
private readonly
|
|
560
|
+
private readonly maintenance;
|
|
543
561
|
private readonly ttlResolver;
|
|
544
562
|
private readonly circuitBreakerManager;
|
|
563
|
+
private nextOperationId;
|
|
545
564
|
private currentGeneration?;
|
|
546
|
-
private readonly writeBehindQueue;
|
|
547
|
-
private writeBehindTimer?;
|
|
548
|
-
private writeBehindFlushPromise?;
|
|
549
|
-
private generationCleanupPromise?;
|
|
550
|
-
private clearEpoch;
|
|
551
565
|
private isDisconnecting;
|
|
552
566
|
private disconnectPromise?;
|
|
553
567
|
constructor(layers: CacheLayer[], options?: CacheStackOptions);
|
|
@@ -643,8 +657,6 @@ declare class CacheStack extends EventEmitter {
|
|
|
643
657
|
private readFromLayers;
|
|
644
658
|
private readLayerEntry;
|
|
645
659
|
private backfill;
|
|
646
|
-
private writeAcrossLayers;
|
|
647
|
-
private executeLayerOperations;
|
|
648
660
|
private resolveFreshTtl;
|
|
649
661
|
private resolveLayerSeconds;
|
|
650
662
|
private shouldNegativeCache;
|
|
@@ -659,25 +671,17 @@ declare class CacheStack extends EventEmitter {
|
|
|
659
671
|
private sleep;
|
|
660
672
|
private withTimeout;
|
|
661
673
|
private shouldBroadcastL1Invalidation;
|
|
662
|
-
private
|
|
663
|
-
private generationCleanupBatchSize;
|
|
674
|
+
private observeOperation;
|
|
664
675
|
private scheduleGenerationCleanup;
|
|
665
676
|
private cleanupGeneration;
|
|
666
677
|
private initializeWriteBehind;
|
|
667
678
|
private shouldWriteBehind;
|
|
668
|
-
private beginClearEpoch;
|
|
669
|
-
private currentKeyEpoch;
|
|
670
|
-
private bumpKeyEpochs;
|
|
671
|
-
private isWriteOutdated;
|
|
672
679
|
private enqueueWriteBehind;
|
|
673
680
|
private flushWriteBehindQueue;
|
|
674
|
-
private
|
|
675
|
-
private intersectKeys;
|
|
681
|
+
private runWriteBehindBatch;
|
|
676
682
|
private qualifyKey;
|
|
677
683
|
private qualifyPattern;
|
|
678
684
|
private stripQualifiedKey;
|
|
679
|
-
private generationPrefix;
|
|
680
|
-
private deleteKeysFromLayers;
|
|
681
685
|
private validateConfiguration;
|
|
682
686
|
private validateWriteOptions;
|
|
683
687
|
private assertActive;
|
|
@@ -690,14 +694,9 @@ declare class CacheStack extends EventEmitter {
|
|
|
690
694
|
private recordCircuitFailure;
|
|
691
695
|
private isNegativeStoredValue;
|
|
692
696
|
private emitError;
|
|
693
|
-
private isCacheSnapshotEntries;
|
|
694
|
-
private sanitizeSnapshotValue;
|
|
695
697
|
private snapshotMaxBytes;
|
|
696
698
|
private snapshotMaxEntries;
|
|
697
699
|
private invalidationMaxKeys;
|
|
698
|
-
private collectKeysForTag;
|
|
699
|
-
private assertWithinInvalidationKeyLimit;
|
|
700
|
-
private visitExportEntries;
|
|
701
700
|
}
|
|
702
701
|
|
|
703
702
|
interface HonoLikeRequest {
|
|
@@ -352,6 +352,21 @@ interface CacheStackEvents {
|
|
|
352
352
|
warm: {
|
|
353
353
|
key: string;
|
|
354
354
|
};
|
|
355
|
+
/** Fired immediately before a high-level cache operation begins. */
|
|
356
|
+
'operation-start': {
|
|
357
|
+
id: number;
|
|
358
|
+
name: string;
|
|
359
|
+
attributes?: Record<string, unknown>;
|
|
360
|
+
};
|
|
361
|
+
/** Fired after a high-level cache operation finishes. */
|
|
362
|
+
'operation-end': {
|
|
363
|
+
id: number;
|
|
364
|
+
name: string;
|
|
365
|
+
attributes?: Record<string, unknown>;
|
|
366
|
+
success: boolean;
|
|
367
|
+
result?: 'null';
|
|
368
|
+
error?: unknown;
|
|
369
|
+
};
|
|
355
370
|
/** Fired when an error occurs (layer failure, circuit breaker, etc.). */
|
|
356
371
|
error: {
|
|
357
372
|
operation: string;
|
|
@@ -537,17 +552,16 @@ declare class CacheStack extends EventEmitter {
|
|
|
537
552
|
private readonly keyDiscovery;
|
|
538
553
|
private readonly fetchRateLimiter;
|
|
539
554
|
private readonly snapshotSerializer;
|
|
555
|
+
private readonly invalidation;
|
|
556
|
+
private readonly layerWriter;
|
|
557
|
+
private readonly snapshots;
|
|
540
558
|
private readonly backgroundRefreshes;
|
|
541
559
|
private readonly layerDegradedUntil;
|
|
542
|
-
private readonly
|
|
560
|
+
private readonly maintenance;
|
|
543
561
|
private readonly ttlResolver;
|
|
544
562
|
private readonly circuitBreakerManager;
|
|
563
|
+
private nextOperationId;
|
|
545
564
|
private currentGeneration?;
|
|
546
|
-
private readonly writeBehindQueue;
|
|
547
|
-
private writeBehindTimer?;
|
|
548
|
-
private writeBehindFlushPromise?;
|
|
549
|
-
private generationCleanupPromise?;
|
|
550
|
-
private clearEpoch;
|
|
551
565
|
private isDisconnecting;
|
|
552
566
|
private disconnectPromise?;
|
|
553
567
|
constructor(layers: CacheLayer[], options?: CacheStackOptions);
|
|
@@ -643,8 +657,6 @@ declare class CacheStack extends EventEmitter {
|
|
|
643
657
|
private readFromLayers;
|
|
644
658
|
private readLayerEntry;
|
|
645
659
|
private backfill;
|
|
646
|
-
private writeAcrossLayers;
|
|
647
|
-
private executeLayerOperations;
|
|
648
660
|
private resolveFreshTtl;
|
|
649
661
|
private resolveLayerSeconds;
|
|
650
662
|
private shouldNegativeCache;
|
|
@@ -659,25 +671,17 @@ declare class CacheStack extends EventEmitter {
|
|
|
659
671
|
private sleep;
|
|
660
672
|
private withTimeout;
|
|
661
673
|
private shouldBroadcastL1Invalidation;
|
|
662
|
-
private
|
|
663
|
-
private generationCleanupBatchSize;
|
|
674
|
+
private observeOperation;
|
|
664
675
|
private scheduleGenerationCleanup;
|
|
665
676
|
private cleanupGeneration;
|
|
666
677
|
private initializeWriteBehind;
|
|
667
678
|
private shouldWriteBehind;
|
|
668
|
-
private beginClearEpoch;
|
|
669
|
-
private currentKeyEpoch;
|
|
670
|
-
private bumpKeyEpochs;
|
|
671
|
-
private isWriteOutdated;
|
|
672
679
|
private enqueueWriteBehind;
|
|
673
680
|
private flushWriteBehindQueue;
|
|
674
|
-
private
|
|
675
|
-
private intersectKeys;
|
|
681
|
+
private runWriteBehindBatch;
|
|
676
682
|
private qualifyKey;
|
|
677
683
|
private qualifyPattern;
|
|
678
684
|
private stripQualifiedKey;
|
|
679
|
-
private generationPrefix;
|
|
680
|
-
private deleteKeysFromLayers;
|
|
681
685
|
private validateConfiguration;
|
|
682
686
|
private validateWriteOptions;
|
|
683
687
|
private assertActive;
|
|
@@ -690,14 +694,9 @@ declare class CacheStack extends EventEmitter {
|
|
|
690
694
|
private recordCircuitFailure;
|
|
691
695
|
private isNegativeStoredValue;
|
|
692
696
|
private emitError;
|
|
693
|
-
private isCacheSnapshotEntries;
|
|
694
|
-
private sanitizeSnapshotValue;
|
|
695
697
|
private snapshotMaxBytes;
|
|
696
698
|
private snapshotMaxEntries;
|
|
697
699
|
private invalidationMaxKeys;
|
|
698
|
-
private collectKeysForTag;
|
|
699
|
-
private assertWithinInvalidationKeyLimit;
|
|
700
|
-
private visitExportEntries;
|
|
701
700
|
}
|
|
702
701
|
|
|
703
702
|
interface HonoLikeRequest {
|
package/dist/edge.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry, t as CacheMetricsSnapshot, w as CacheRateLimitOptions, B as CacheTtlPolicy, D as CacheTtlPolicyContext, J as CacheWriteOptions, K as EvictionPolicy, M as MemoryLayer, N as MemoryLayerOptions, O as MemoryLayerSnapshotEntry, P as PatternMatcher, T as TagIndex, Q as createHonoCacheMiddleware } from './edge-
|
|
1
|
+
export { e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry, t as CacheMetricsSnapshot, w as CacheRateLimitOptions, B as CacheTtlPolicy, D as CacheTtlPolicyContext, J as CacheWriteOptions, K as EvictionPolicy, M as MemoryLayer, N as MemoryLayerOptions, O as MemoryLayerSnapshotEntry, P as PatternMatcher, T as TagIndex, Q as createHonoCacheMiddleware } from './edge-DBs8Ko5W.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, t as CacheMetricsSnapshot, w as CacheRateLimitOptions, B as CacheTtlPolicy, D as CacheTtlPolicyContext, J as CacheWriteOptions, K as EvictionPolicy, M as MemoryLayer, N as MemoryLayerOptions, O as MemoryLayerSnapshotEntry, P as PatternMatcher, T as TagIndex, Q as createHonoCacheMiddleware } from './edge-
|
|
1
|
+
export { e as CacheGetOptions, f as CacheLayer, h as CacheLayerSetManyEntry, t as CacheMetricsSnapshot, w as CacheRateLimitOptions, B as CacheTtlPolicy, D as CacheTtlPolicyContext, J as CacheWriteOptions, K as EvictionPolicy, M as MemoryLayer, N as MemoryLayerOptions, O as MemoryLayerSnapshotEntry, P as PatternMatcher, T as TagIndex, Q as createHonoCacheMiddleware } from './edge-DBs8Ko5W.js';
|
|
2
2
|
import 'node:events';
|