raffel 1.1.70 → 1.1.72
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/dist/cache/defaults.d.ts +9 -0
- package/dist/cache/defaults.d.ts.map +1 -0
- package/dist/cache/defaults.js +9 -0
- package/dist/cache/defaults.js.map +1 -0
- package/dist/cache/expiration-wheel.d.ts +15 -0
- package/dist/cache/expiration-wheel.d.ts.map +1 -0
- package/dist/cache/expiration-wheel.js +65 -0
- package/dist/cache/expiration-wheel.js.map +1 -0
- package/dist/cache/fs-layer.d.ts +14 -0
- package/dist/cache/fs-layer.d.ts.map +1 -0
- package/dist/cache/fs-layer.js +190 -0
- package/dist/cache/fs-layer.js.map +1 -0
- package/dist/cache/index.d.ts +9 -0
- package/dist/cache/index.d.ts.map +1 -1
- package/dist/cache/index.js +4 -0
- package/dist/cache/index.js.map +1 -1
- package/dist/cache/key.d.ts +11 -0
- package/dist/cache/key.d.ts.map +1 -0
- package/dist/cache/key.js +41 -0
- package/dist/cache/key.js.map +1 -0
- package/dist/cache/redis-layer.d.ts +30 -0
- package/dist/cache/redis-layer.d.ts.map +1 -0
- package/dist/cache/redis-layer.js +108 -0
- package/dist/cache/redis-layer.js.map +1 -0
- package/dist/cache/server-runtime.d.ts +74 -0
- package/dist/cache/server-runtime.d.ts.map +1 -0
- package/dist/cache/server-runtime.js +220 -0
- package/dist/cache/server-runtime.js.map +1 -0
- package/dist/cache/tiered.d.ts +86 -0
- package/dist/cache/tiered.d.ts.map +1 -0
- package/dist/cache/tiered.js +681 -0
- package/dist/cache/tiered.js.map +1 -0
- package/dist/cache/write-behind-queue.d.ts +34 -0
- package/dist/cache/write-behind-queue.d.ts.map +1 -0
- package/dist/cache/write-behind-queue.js +115 -0
- package/dist/cache/write-behind-queue.js.map +1 -0
- package/dist/http/app.d.ts.map +1 -1
- package/dist/http/app.js +1 -0
- package/dist/http/app.js.map +1 -1
- package/dist/http/cache.d.ts +22 -0
- package/dist/http/cache.d.ts.map +1 -0
- package/dist/http/cache.js +183 -0
- package/dist/http/cache.js.map +1 -0
- package/dist/http/index.d.ts +2 -0
- package/dist/http/index.d.ts.map +1 -1
- package/dist/http/index.js +1 -0
- package/dist/http/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/server/builder/operation-registrar.d.ts +3 -0
- package/dist/server/builder/operation-registrar.d.ts.map +1 -1
- package/dist/server/builder/operation-registrar.js +7 -2
- package/dist/server/builder/operation-registrar.js.map +1 -1
- package/dist/server/builder/programmatic-registration.d.ts +2 -0
- package/dist/server/builder/programmatic-registration.d.ts.map +1 -1
- package/dist/server/builder/programmatic-registration.js +13 -2
- package/dist/server/builder/programmatic-registration.js.map +1 -1
- package/dist/server/builder.d.ts.map +1 -1
- package/dist/server/builder.js +17 -3
- package/dist/server/builder.js.map +1 -1
- package/dist/server/discovery-utils.d.ts +2 -1
- package/dist/server/discovery-utils.d.ts.map +1 -1
- package/dist/server/discovery-utils.js +10 -2
- package/dist/server/discovery-utils.js.map +1 -1
- package/dist/server/fs-routes/types.d.ts +3 -0
- package/dist/server/fs-routes/types.d.ts.map +1 -1
- package/dist/server/handler-builders.d.ts +2 -0
- package/dist/server/handler-builders.d.ts.map +1 -1
- package/dist/server/handler-builders.js +7 -0
- package/dist/server/handler-builders.js.map +1 -1
- package/dist/server/interceptor-utils.d.ts +2 -0
- package/dist/server/interceptor-utils.d.ts.map +1 -1
- package/dist/server/interceptor-utils.js +25 -1
- package/dist/server/interceptor-utils.js.map +1 -1
- package/dist/server/router-module.d.ts +3 -0
- package/dist/server/router-module.d.ts.map +1 -1
- package/dist/server/router-module.js +1 -0
- package/dist/server/router-module.js.map +1 -1
- package/dist/server/types/config-types.d.ts +3 -0
- package/dist/server/types/config-types.d.ts.map +1 -1
- package/dist/server/types/handler-types.d.ts +7 -0
- package/dist/server/types/handler-types.d.ts.map +1 -1
- package/dist/server/types/lifecycle-types.d.ts +2 -0
- package/dist/server/types/lifecycle-types.d.ts.map +1 -1
- package/dist/server/types/protocol-namespace-types.d.ts +3 -0
- package/dist/server/types/protocol-namespace-types.d.ts.map +1 -1
- package/dist/ui/cache/defaults.d.ts +9 -0
- package/dist/ui/cache/defaults.d.ts.map +1 -0
- package/dist/ui/cache/expiration-wheel.d.ts +15 -0
- package/dist/ui/cache/expiration-wheel.d.ts.map +1 -0
- package/dist/ui/cache/fs-layer.d.ts +14 -0
- package/dist/ui/cache/fs-layer.d.ts.map +1 -0
- package/dist/ui/cache/key.d.ts +11 -0
- package/dist/ui/cache/key.d.ts.map +1 -0
- package/dist/ui/cache/server-runtime.d.ts +74 -0
- package/dist/ui/cache/server-runtime.d.ts.map +1 -0
- package/dist/ui/cache/tiered.d.ts +86 -0
- package/dist/ui/cache/tiered.d.ts.map +1 -0
- package/dist/ui/cache/write-behind-queue.d.ts +34 -0
- package/dist/ui/cache/write-behind-queue.d.ts.map +1 -0
- package/dist/ui/server/fs-routes/types.d.ts +3 -0
- package/dist/ui/server/fs-routes/types.d.ts.map +1 -1
- package/dist/ui/validation/index.d.ts +1 -1
- package/dist/ui/validation/index.d.ts.map +1 -1
- package/dist/ui/validation/schema.d.ts +7 -0
- package/dist/ui/validation/schema.d.ts.map +1 -1
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +1 -1
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/schema.d.ts +7 -0
- package/dist/validation/schema.d.ts.map +1 -1
- package/dist/validation/schema.js +36 -2
- package/dist/validation/schema.js.map +1 -1
- package/package.json +5 -1
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const DEFAULT_L1_MAX_MEMORY_BYTES: number;
|
|
2
|
+
export declare const DEFAULT_L1_MAX_ENTRIES = 10000;
|
|
3
|
+
export declare const DEFAULT_L2_MAX_SIZE_BYTES: number;
|
|
4
|
+
export declare const DEFAULT_L2_MAX_FILES = 50000;
|
|
5
|
+
export declare const DEFAULT_CACHE_READ_TIMEOUT_MS = 250;
|
|
6
|
+
export declare const DEFAULT_CACHE_OPERATION_TIMEOUT_MS = 1000;
|
|
7
|
+
export declare const DEFAULT_CACHE_CIRCUIT_FAILURE_THRESHOLD = 3;
|
|
8
|
+
export declare const DEFAULT_CACHE_CIRCUIT_COOLDOWN_MS = 10000;
|
|
9
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/cache/defaults.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,2BAA2B,QAAmB,CAAA;AAC3D,eAAO,MAAM,sBAAsB,QAAS,CAAA;AAC5C,eAAO,MAAM,yBAAyB,QAAmB,CAAA;AACzD,eAAO,MAAM,oBAAoB,QAAS,CAAA;AAC1C,eAAO,MAAM,6BAA6B,MAAM,CAAA;AAChD,eAAO,MAAM,kCAAkC,OAAQ,CAAA;AACvD,eAAO,MAAM,uCAAuC,IAAI,CAAA;AACxD,eAAO,MAAM,iCAAiC,QAAS,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const DEFAULT_L1_MAX_MEMORY_BYTES = 16 * 1024 * 1024;
|
|
2
|
+
export const DEFAULT_L1_MAX_ENTRIES = 10_000;
|
|
3
|
+
export const DEFAULT_L2_MAX_SIZE_BYTES = 64 * 1024 * 1024;
|
|
4
|
+
export const DEFAULT_L2_MAX_FILES = 50_000;
|
|
5
|
+
export const DEFAULT_CACHE_READ_TIMEOUT_MS = 250;
|
|
6
|
+
export const DEFAULT_CACHE_OPERATION_TIMEOUT_MS = 1_000;
|
|
7
|
+
export const DEFAULT_CACHE_CIRCUIT_FAILURE_THRESHOLD = 3;
|
|
8
|
+
export const DEFAULT_CACHE_CIRCUIT_COOLDOWN_MS = 10_000;
|
|
9
|
+
//# sourceMappingURL=defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/cache/defaults.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,2BAA2B,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAA;AAC3D,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAA;AAC5C,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAA;AACzD,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAA;AAC1C,MAAM,CAAC,MAAM,6BAA6B,GAAG,GAAG,CAAA;AAChD,MAAM,CAAC,MAAM,kCAAkC,GAAG,KAAK,CAAA;AACvD,MAAM,CAAC,MAAM,uCAAuC,GAAG,CAAC,CAAA;AACxD,MAAM,CAAC,MAAM,iCAAiC,GAAG,MAAM,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export declare class ExpirationWheel {
|
|
2
|
+
private readonly resolutionMs;
|
|
3
|
+
private readonly onExpire;
|
|
4
|
+
private readonly slots;
|
|
5
|
+
private readonly scheduled;
|
|
6
|
+
private readonly timer;
|
|
7
|
+
private currentTick;
|
|
8
|
+
constructor(resolutionMs: number, onExpire: (key: string, version: number) => void, wheelSize?: number);
|
|
9
|
+
schedule(key: string, expiresAt: number, version: number): void;
|
|
10
|
+
cancel(key: string): void;
|
|
11
|
+
shutdown(): void;
|
|
12
|
+
private advance;
|
|
13
|
+
private expire;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=expiration-wheel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expiration-wheel.d.ts","sourceRoot":"","sources":["../../src/cache/expiration-wheel.ts"],"names":[],"mappings":"AAMA,qBAAa,eAAe;IAOxB,OAAO,CAAC,QAAQ,CAAC,YAAY;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAP3B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAqC;IAC/D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD,OAAO,CAAC,WAAW,CAAQ;gBAGR,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,EACjE,SAAS,SAAM;IAQjB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ/D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAOzB,QAAQ,IAAI,IAAI;IAMhB,OAAO,CAAC,OAAO;IAuBf,OAAO,CAAC,MAAM;CAKf"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export class ExpirationWheel {
|
|
2
|
+
resolutionMs;
|
|
3
|
+
onExpire;
|
|
4
|
+
slots;
|
|
5
|
+
scheduled = new Map();
|
|
6
|
+
timer;
|
|
7
|
+
currentTick;
|
|
8
|
+
constructor(resolutionMs, onExpire, wheelSize = 256) {
|
|
9
|
+
this.resolutionMs = resolutionMs;
|
|
10
|
+
this.onExpire = onExpire;
|
|
11
|
+
this.slots = Array.from({ length: wheelSize }, () => new Set());
|
|
12
|
+
this.currentTick = Math.floor(Date.now() / resolutionMs);
|
|
13
|
+
this.timer = setInterval(() => this.advance(), resolutionMs);
|
|
14
|
+
this.timer.unref();
|
|
15
|
+
}
|
|
16
|
+
schedule(key, expiresAt, version) {
|
|
17
|
+
this.cancel(key);
|
|
18
|
+
const dueTick = Math.ceil(expiresAt / this.resolutionMs);
|
|
19
|
+
const slot = dueTick % this.slots.length;
|
|
20
|
+
this.slots[slot].add(key);
|
|
21
|
+
this.scheduled.set(key, { dueTick, slot, version });
|
|
22
|
+
}
|
|
23
|
+
cancel(key) {
|
|
24
|
+
const expiry = this.scheduled.get(key);
|
|
25
|
+
if (!expiry)
|
|
26
|
+
return;
|
|
27
|
+
this.slots[expiry.slot].delete(key);
|
|
28
|
+
this.scheduled.delete(key);
|
|
29
|
+
}
|
|
30
|
+
shutdown() {
|
|
31
|
+
clearInterval(this.timer);
|
|
32
|
+
this.scheduled.clear();
|
|
33
|
+
for (const slot of this.slots)
|
|
34
|
+
slot.clear();
|
|
35
|
+
}
|
|
36
|
+
advance() {
|
|
37
|
+
const targetTick = Math.floor(Date.now() / this.resolutionMs);
|
|
38
|
+
const elapsed = targetTick - this.currentTick;
|
|
39
|
+
if (elapsed <= 0)
|
|
40
|
+
return;
|
|
41
|
+
if (elapsed > this.slots.length) {
|
|
42
|
+
this.currentTick = targetTick;
|
|
43
|
+
for (const [key, expiry] of this.scheduled) {
|
|
44
|
+
if (expiry.dueTick <= targetTick)
|
|
45
|
+
this.expire(key, expiry);
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
while (this.currentTick < targetTick) {
|
|
50
|
+
this.currentTick++;
|
|
51
|
+
const slotIndex = this.currentTick % this.slots.length;
|
|
52
|
+
for (const key of [...this.slots[slotIndex]]) {
|
|
53
|
+
const expiry = this.scheduled.get(key);
|
|
54
|
+
if (expiry && expiry.dueTick <= this.currentTick)
|
|
55
|
+
this.expire(key, expiry);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
expire(key, expiry) {
|
|
60
|
+
this.slots[expiry.slot].delete(key);
|
|
61
|
+
this.scheduled.delete(key);
|
|
62
|
+
this.onExpire(key, expiry.version);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=expiration-wheel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expiration-wheel.js","sourceRoot":"","sources":["../../src/cache/expiration-wheel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type CacheCircuitBreakerOptions, type CacheLayer } from './tiered.js';
|
|
2
|
+
export interface FileSystemCacheLayerOptions {
|
|
3
|
+
id: string;
|
|
4
|
+
directory: string;
|
|
5
|
+
ttlMs: number;
|
|
6
|
+
maxSizeBytes?: number;
|
|
7
|
+
maxFiles?: number;
|
|
8
|
+
expirationResolutionMs?: number;
|
|
9
|
+
readTimeoutMs?: number;
|
|
10
|
+
operationTimeoutMs?: number;
|
|
11
|
+
circuitBreaker?: CacheCircuitBreakerOptions;
|
|
12
|
+
}
|
|
13
|
+
export declare function createFileSystemCacheLayer(options: FileSystemCacheLayerOptions): CacheLayer;
|
|
14
|
+
//# sourceMappingURL=fs-layer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-layer.d.ts","sourceRoot":"","sources":["../../src/cache/fs-layer.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,UAAU,EAEhB,MAAM,aAAa,CAAA;AAUpB,MAAM,WAAW,2BAA2B;IAC1C,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,cAAc,CAAC,EAAE,0BAA0B,CAAA;CAC5C;AAmBD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,2BAA2B,GAAG,UAAU,CAgL3F"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { mkdir, readFile, readdir, rename, unlink, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { ExpirationWheel } from './expiration-wheel.js';
|
|
5
|
+
import { isCacheRecord, } from './tiered.js';
|
|
6
|
+
import { DEFAULT_CACHE_CIRCUIT_COOLDOWN_MS, DEFAULT_CACHE_CIRCUIT_FAILURE_THRESHOLD, DEFAULT_CACHE_OPERATION_TIMEOUT_MS, DEFAULT_CACHE_READ_TIMEOUT_MS, DEFAULT_L2_MAX_FILES, DEFAULT_L2_MAX_SIZE_BYTES, } from './defaults.js';
|
|
7
|
+
function hashedPath(directory, key) {
|
|
8
|
+
const hash = createHash('sha256').update(key).digest('hex');
|
|
9
|
+
return join(directory, hash.slice(0, 2), `${hash.slice(2)}.cache`);
|
|
10
|
+
}
|
|
11
|
+
export function createFileSystemCacheLayer(options) {
|
|
12
|
+
if (options.ttlMs <= 0)
|
|
13
|
+
throw new Error('Filesystem cache ttlMs must be greater than zero');
|
|
14
|
+
if (options.maxFiles !== undefined && options.maxFiles <= 0) {
|
|
15
|
+
throw new Error('Filesystem cache maxFiles must be greater than zero');
|
|
16
|
+
}
|
|
17
|
+
if (options.maxSizeBytes !== undefined && options.maxSizeBytes <= 0) {
|
|
18
|
+
throw new Error('Filesystem cache maxSizeBytes must be greater than zero');
|
|
19
|
+
}
|
|
20
|
+
const maxSizeBytes = options.maxSizeBytes ?? DEFAULT_L2_MAX_SIZE_BYTES;
|
|
21
|
+
const maxFiles = options.maxFiles ?? DEFAULT_L2_MAX_FILES;
|
|
22
|
+
const index = new Map();
|
|
23
|
+
let totalSizeBytes = 0;
|
|
24
|
+
let hits = 0;
|
|
25
|
+
let misses = 0;
|
|
26
|
+
const wheel = new ExpirationWheel(options.expirationResolutionMs ?? 1_000, (key, version) => {
|
|
27
|
+
if (index.get(key)?.version === version)
|
|
28
|
+
void remove(key);
|
|
29
|
+
});
|
|
30
|
+
let initializationError;
|
|
31
|
+
const ready = initialize().catch((error) => {
|
|
32
|
+
initializationError = error;
|
|
33
|
+
});
|
|
34
|
+
async function ensureReady() {
|
|
35
|
+
await ready;
|
|
36
|
+
if (initializationError)
|
|
37
|
+
throw initializationError;
|
|
38
|
+
}
|
|
39
|
+
async function initialize() {
|
|
40
|
+
await mkdir(options.directory, { recursive: true });
|
|
41
|
+
const recovered = [];
|
|
42
|
+
for (const shard of await readdir(options.directory, { withFileTypes: true })) {
|
|
43
|
+
if (!shard.isDirectory())
|
|
44
|
+
continue;
|
|
45
|
+
const shardPath = join(options.directory, shard.name);
|
|
46
|
+
for (const file of await readdir(shardPath, { withFileTypes: true })) {
|
|
47
|
+
if (!file.isFile() || !file.name.endsWith('.cache'))
|
|
48
|
+
continue;
|
|
49
|
+
const filePath = join(shardPath, file.name);
|
|
50
|
+
try {
|
|
51
|
+
const content = await readFile(filePath);
|
|
52
|
+
const stored = JSON.parse(content.toString('utf8'));
|
|
53
|
+
if (typeof stored.key !== 'string' || !isCacheRecord(stored.record)) {
|
|
54
|
+
throw new Error('Invalid cache record');
|
|
55
|
+
}
|
|
56
|
+
const expiresAt = stored.record.staleUntil ?? stored.record.expiresAt;
|
|
57
|
+
if (Date.now() >= expiresAt) {
|
|
58
|
+
await unlink(filePath);
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
recovered.push([
|
|
62
|
+
stored.key,
|
|
63
|
+
{
|
|
64
|
+
path: filePath,
|
|
65
|
+
sizeBytes: content.byteLength,
|
|
66
|
+
createdAt: stored.record.createdAt,
|
|
67
|
+
version: stored.record.version,
|
|
68
|
+
},
|
|
69
|
+
expiresAt,
|
|
70
|
+
]);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
await unlink(filePath).catch(() => undefined);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
recovered.sort((left, right) => left[1].createdAt - right[1].createdAt);
|
|
78
|
+
for (const [key, metadata, expiresAt] of recovered) {
|
|
79
|
+
index.set(key, metadata);
|
|
80
|
+
totalSizeBytes += metadata.sizeBytes;
|
|
81
|
+
wheel.schedule(key, expiresAt, metadata.version);
|
|
82
|
+
}
|
|
83
|
+
await enforceLimits(0);
|
|
84
|
+
}
|
|
85
|
+
async function remove(key) {
|
|
86
|
+
const metadata = index.get(key);
|
|
87
|
+
if (!metadata)
|
|
88
|
+
return;
|
|
89
|
+
index.delete(key);
|
|
90
|
+
totalSizeBytes -= metadata.sizeBytes;
|
|
91
|
+
wheel.cancel(key);
|
|
92
|
+
await unlink(metadata.path).catch(() => undefined);
|
|
93
|
+
}
|
|
94
|
+
async function enforceLimits(incomingBytes) {
|
|
95
|
+
if (incomingBytes > maxSizeBytes)
|
|
96
|
+
return false;
|
|
97
|
+
while (totalSizeBytes + incomingBytes > maxSizeBytes || index.size >= maxFiles) {
|
|
98
|
+
const oldest = index.keys().next().value;
|
|
99
|
+
if (oldest === undefined)
|
|
100
|
+
break;
|
|
101
|
+
await remove(oldest);
|
|
102
|
+
}
|
|
103
|
+
return totalSizeBytes + incomingBytes <= maxSizeBytes;
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
id: options.id,
|
|
107
|
+
ttlMs: options.ttlMs,
|
|
108
|
+
readTimeoutMs: options.readTimeoutMs ?? DEFAULT_CACHE_READ_TIMEOUT_MS,
|
|
109
|
+
operationTimeoutMs: options.operationTimeoutMs ?? DEFAULT_CACHE_OPERATION_TIMEOUT_MS,
|
|
110
|
+
circuitBreaker: options.circuitBreaker ?? {
|
|
111
|
+
failureThreshold: DEFAULT_CACHE_CIRCUIT_FAILURE_THRESHOLD,
|
|
112
|
+
cooldownMs: DEFAULT_CACHE_CIRCUIT_COOLDOWN_MS,
|
|
113
|
+
},
|
|
114
|
+
async get(key) {
|
|
115
|
+
await ensureReady();
|
|
116
|
+
const filePath = hashedPath(options.directory, key);
|
|
117
|
+
try {
|
|
118
|
+
const stored = JSON.parse(await readFile(filePath, 'utf8'));
|
|
119
|
+
if (typeof stored.key !== 'string' || !isCacheRecord(stored.record)) {
|
|
120
|
+
throw new Error('Invalid cache record');
|
|
121
|
+
}
|
|
122
|
+
const expiresAt = stored.record.staleUntil ?? stored.record.expiresAt;
|
|
123
|
+
if (stored.key !== key || Date.now() >= expiresAt) {
|
|
124
|
+
await remove(key);
|
|
125
|
+
misses++;
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
hits++;
|
|
129
|
+
return stored.record;
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
await remove(key);
|
|
133
|
+
misses++;
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
async set(key, record, ttlMs, staleMs = 0) {
|
|
138
|
+
await ensureReady();
|
|
139
|
+
const expiresAt = Date.now() + ttlMs;
|
|
140
|
+
const stored = {
|
|
141
|
+
key,
|
|
142
|
+
record: {
|
|
143
|
+
...record,
|
|
144
|
+
expiresAt,
|
|
145
|
+
staleUntil: staleMs > 0 ? expiresAt + staleMs : undefined,
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
const encoded = Buffer.from(JSON.stringify(stored));
|
|
149
|
+
await remove(key);
|
|
150
|
+
if (!(await enforceLimits(encoded.byteLength)))
|
|
151
|
+
return;
|
|
152
|
+
const filePath = hashedPath(options.directory, key);
|
|
153
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
154
|
+
const temporaryPath = `${filePath}.${randomUUID()}.tmp`;
|
|
155
|
+
try {
|
|
156
|
+
await writeFile(temporaryPath, encoded);
|
|
157
|
+
await rename(temporaryPath, filePath);
|
|
158
|
+
}
|
|
159
|
+
finally {
|
|
160
|
+
await unlink(temporaryPath).catch(() => undefined);
|
|
161
|
+
}
|
|
162
|
+
index.set(key, {
|
|
163
|
+
path: filePath,
|
|
164
|
+
sizeBytes: encoded.byteLength,
|
|
165
|
+
createdAt: record.createdAt,
|
|
166
|
+
version: record.version,
|
|
167
|
+
});
|
|
168
|
+
totalSizeBytes += encoded.byteLength;
|
|
169
|
+
wheel.schedule(key, stored.record.staleUntil ?? expiresAt, record.version);
|
|
170
|
+
},
|
|
171
|
+
async delete(key) {
|
|
172
|
+
await ensureReady();
|
|
173
|
+
await remove(key);
|
|
174
|
+
},
|
|
175
|
+
async clearNamespace(namespace) {
|
|
176
|
+
await ensureReady();
|
|
177
|
+
await Promise.all([...index.keys()]
|
|
178
|
+
.filter((key) => key.startsWith(`${namespace}:`))
|
|
179
|
+
.map((key) => remove(key)));
|
|
180
|
+
},
|
|
181
|
+
stats() {
|
|
182
|
+
return { totalItems: index.size, storageUsageBytes: totalSizeBytes, hits, misses };
|
|
183
|
+
},
|
|
184
|
+
async shutdown() {
|
|
185
|
+
await ready;
|
|
186
|
+
wheel.shutdown();
|
|
187
|
+
},
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=fs-layer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fs-layer.js","sourceRoot":"","sources":["../../src/cache/fs-layer.ts"],"names":[],"mappings":"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"}
|
package/dist/cache/index.d.ts
CHANGED
|
@@ -54,4 +54,13 @@
|
|
|
54
54
|
export type { CacheDriver, CacheEntry, CacheGetResult, CacheStats, MemoryStats, CompressionStats, EvictionPolicy, CompressionConfig, MemoryDriverOptions, FileDriverOptions, RedisDriverOptions, RedisLikeClient, CacheDriverType, CacheDriverConfig, EvictionInfo, PressureInfo, } from './types.js';
|
|
55
55
|
export { createDriver, createDriverFromConfig, createDriverSync, DRIVER_TYPES, isValidDriverType, } from './factory.js';
|
|
56
56
|
export { MemoryDriver, createMemoryDriver, FileDriver, createFileDriver, RedisDriver, createRedisDriver, } from './drivers/index.js';
|
|
57
|
+
export { createTieredCache, createMemoryCacheLayer, createFileSystemCacheLayer, DEFAULT_CACHE_CIRCUIT_COOLDOWN_MS, DEFAULT_CACHE_CIRCUIT_FAILURE_THRESHOLD, DEFAULT_CACHE_OPERATION_TIMEOUT_MS, DEFAULT_CACHE_READ_TIMEOUT_MS, DEFAULT_L1_MAX_ENTRIES, DEFAULT_L1_MAX_MEMORY_BYTES, DEFAULT_L2_MAX_FILES, DEFAULT_L2_MAX_SIZE_BYTES, } from './tiered.js';
|
|
58
|
+
export { createRedisCacheLayer } from './redis-layer.js';
|
|
59
|
+
export { procedureCacheKey, procedureCacheKeyFor } from './key.js';
|
|
60
|
+
export type { CacheLayer, CacheCircuitBreakerOptions, CacheLayerStats, CacheLookup, CacheRecord, CacheWriteOptions, MemoryCacheLayerOptions, TieredCache, TieredCacheOptions, } from './tiered.js';
|
|
61
|
+
export type { FileSystemCacheLayerOptions } from './fs-layer.js';
|
|
62
|
+
export type { RedisCacheLayerClient, RedisCacheLayerOptions } from './redis-layer.js';
|
|
63
|
+
export type { CacheIdentityScope } from './key.js';
|
|
64
|
+
export type { CacheRule, FileSystemLayerConfig, MemoryLayerConfig, ProviderLayerConfig, RouteCacheConfig, ServerCacheConfig, ServerCacheController, ServerCacheLayerConfig, } from './server-runtime.js';
|
|
65
|
+
export type { WriteBehindQueueOptions, WriteBehindQueueStats } from './write-behind-queue.js';
|
|
57
66
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAGH,YAAY,EACV,WAAW,EACX,UAAU,EACV,cAAc,EACd,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,YAAY,GACb,MAAM,YAAY,CAAA;AAGnB,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,GAClB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,iBAAiB,GAClB,MAAM,oBAAoB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAGH,YAAY,EACV,WAAW,EACX,UAAU,EACV,cAAc,EACd,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,YAAY,GACb,MAAM,YAAY,CAAA;AAGnB,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,GAClB,MAAM,cAAc,CAAA;AAGrB,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,iBAAiB,GAClB,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,0BAA0B,EAC1B,iCAAiC,EACjC,uCAAuC,EACvC,kCAAkC,EAClC,6BAA6B,EAC7B,sBAAsB,EACtB,2BAA2B,EAC3B,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAClE,YAAY,EACV,UAAU,EACV,0BAA0B,EAC1B,eAAe,EACf,WAAW,EACX,WAAW,EACX,iBAAiB,EACjB,uBAAuB,EACvB,WAAW,EACX,kBAAkB,GACnB,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAA;AAChE,YAAY,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAA;AACrF,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAClD,YAAY,EACV,SAAS,EACT,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA"}
|
package/dist/cache/index.js
CHANGED
|
@@ -55,4 +55,8 @@
|
|
|
55
55
|
export { createDriver, createDriverFromConfig, createDriverSync, DRIVER_TYPES, isValidDriverType, } from './factory.js';
|
|
56
56
|
// Drivers (for direct import when needed)
|
|
57
57
|
export { MemoryDriver, createMemoryDriver, FileDriver, createFileDriver, RedisDriver, createRedisDriver, } from './drivers/index.js';
|
|
58
|
+
// Hierarchical response cache (L1 memory → L2 filesystem → L3 provider)
|
|
59
|
+
export { createTieredCache, createMemoryCacheLayer, createFileSystemCacheLayer, DEFAULT_CACHE_CIRCUIT_COOLDOWN_MS, DEFAULT_CACHE_CIRCUIT_FAILURE_THRESHOLD, DEFAULT_CACHE_OPERATION_TIMEOUT_MS, DEFAULT_CACHE_READ_TIMEOUT_MS, DEFAULT_L1_MAX_ENTRIES, DEFAULT_L1_MAX_MEMORY_BYTES, DEFAULT_L2_MAX_FILES, DEFAULT_L2_MAX_SIZE_BYTES, } from './tiered.js';
|
|
60
|
+
export { createRedisCacheLayer } from './redis-layer.js';
|
|
61
|
+
export { procedureCacheKey, procedureCacheKeyFor } from './key.js';
|
|
58
62
|
//# sourceMappingURL=index.js.map
|
package/dist/cache/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAsBH,UAAU;AACV,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,GAClB,MAAM,cAAc,CAAA;AAErB,0CAA0C;AAC1C,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,iBAAiB,GAClB,MAAM,oBAAoB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cache/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAsBH,UAAU;AACV,OAAO,EACL,YAAY,EACZ,sBAAsB,EACtB,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,GAClB,MAAM,cAAc,CAAA;AAErB,0CAA0C;AAC1C,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,iBAAiB,GAClB,MAAM,oBAAoB,CAAA;AAE3B,wEAAwE;AACxE,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,0BAA0B,EAC1B,iCAAiC,EACjC,uCAAuC,EACvC,kCAAkC,EAClC,6BAA6B,EAC7B,sBAAsB,EACtB,2BAA2B,EAC3B,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAA;AACxD,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Context, Envelope } from '../types/index.js';
|
|
2
|
+
export type CacheIdentityScope = 'auto' | 'public' | 'tenant' | 'principal';
|
|
3
|
+
export declare function procedureCacheKey(envelope: Envelope, ctx: Context, options?: {
|
|
4
|
+
scope?: CacheIdentityScope;
|
|
5
|
+
version?: string;
|
|
6
|
+
}): string | undefined;
|
|
7
|
+
export declare function procedureCacheKeyFor(procedure: string, input: unknown, ctx: Context, options?: {
|
|
8
|
+
scope?: CacheIdentityScope;
|
|
9
|
+
version?: string;
|
|
10
|
+
}): string | undefined;
|
|
11
|
+
//# sourceMappingURL=key.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key.d.ts","sourceRoot":"","sources":["../../src/cache/key.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAE1D,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAA;AA6B3E,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7D,MAAM,GAAG,SAAS,CAEpB;AAED,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7D,MAAM,GAAG,SAAS,CAMpB"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { deriveAuthPrincipalId, deriveAuthTenantId } from '../auth/principal.js';
|
|
3
|
+
function stableJson(value) {
|
|
4
|
+
try {
|
|
5
|
+
return JSON.stringify(value, (_key, current) => {
|
|
6
|
+
if (!current || typeof current !== 'object' || Array.isArray(current))
|
|
7
|
+
return current;
|
|
8
|
+
return Object.fromEntries(Object.entries(current).sort(([left], [right]) => left.localeCompare(right)));
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
function identityFor(ctx, scope) {
|
|
16
|
+
if (scope === 'public')
|
|
17
|
+
return 'public';
|
|
18
|
+
const principal = deriveAuthPrincipalId(ctx.auth);
|
|
19
|
+
const tenant = deriveAuthTenantId(ctx.auth);
|
|
20
|
+
if (scope === 'tenant')
|
|
21
|
+
return tenant ? `tenant:${tenant}` : undefined;
|
|
22
|
+
if (scope === 'principal')
|
|
23
|
+
return principal
|
|
24
|
+
? `tenant:${tenant ?? '-'}:principal:${principal}`
|
|
25
|
+
: undefined;
|
|
26
|
+
if (!ctx.auth.authenticated)
|
|
27
|
+
return 'anonymous';
|
|
28
|
+
return principal ? `tenant:${tenant ?? '-'}:principal:${principal}` : undefined;
|
|
29
|
+
}
|
|
30
|
+
export function procedureCacheKey(envelope, ctx, options = {}) {
|
|
31
|
+
return procedureCacheKeyFor(envelope.procedure, envelope.payload, ctx, options);
|
|
32
|
+
}
|
|
33
|
+
export function procedureCacheKeyFor(procedure, input, ctx, options = {}) {
|
|
34
|
+
const payload = stableJson(input);
|
|
35
|
+
const identity = identityFor(ctx, options.scope ?? 'auto');
|
|
36
|
+
if (payload === undefined || identity === undefined)
|
|
37
|
+
return undefined;
|
|
38
|
+
const digest = createHash('sha256').update(payload).digest('base64url');
|
|
39
|
+
return `procedure:${procedure}:v${options.version ?? '1'}:${identity}:${digest}`;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"key.js","sourceRoot":"","sources":["../../src/cache/key.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAKhF,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YAC7C,IAAI,CAAC,OAAO,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;gBAAE,OAAO,OAAO,CAAA;YACrF,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,OAAkC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAC1E,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAC1B,CACF,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,GAAY,EAAE,KAAyB;IAC1D,IAAI,KAAK,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAA;IACvC,MAAM,SAAS,GAAG,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACjD,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IAC3C,IAAI,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,CAAC,CAAC,UAAU,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;IACtE,IAAI,KAAK,KAAK,WAAW;QAAE,OAAO,SAAS;YACzC,CAAC,CAAC,UAAU,MAAM,IAAI,GAAG,cAAc,SAAS,EAAE;YAClD,CAAC,CAAC,SAAS,CAAA;IACb,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa;QAAE,OAAO,WAAW,CAAA;IAC/C,OAAO,SAAS,CAAC,CAAC,CAAC,UAAU,MAAM,IAAI,GAAG,cAAc,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;AACjF,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,QAAkB,EAClB,GAAY,EACZ,UAA4D,EAAE;IAE9D,OAAO,oBAAoB,CAAC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,CAAA;AACjF,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,SAAiB,EACjB,KAAc,EACd,GAAY,EACZ,UAA4D,EAAE;IAE9D,MAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAA;IACjC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,CAAA;IAC1D,IAAI,OAAO,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IACrE,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IACvE,OAAO,aAAa,SAAS,KAAK,OAAO,CAAC,OAAO,IAAI,GAAG,IAAI,QAAQ,IAAI,MAAM,EAAE,CAAA;AAClF,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type CacheCircuitBreakerOptions, type CacheLayer } from './tiered.js';
|
|
2
|
+
export interface RedisCacheLayerClient {
|
|
3
|
+
get(key: string): Promise<string | null>;
|
|
4
|
+
set?(key: string, value: string, ...args: any[]): Promise<unknown>;
|
|
5
|
+
pSetEx?(key: string, milliseconds: number, value: string): Promise<unknown>;
|
|
6
|
+
del(key: string | string[]): Promise<number>;
|
|
7
|
+
scan?(cursor: string | number, ...args: any[]): Promise<[string | number, string[]] | {
|
|
8
|
+
cursor: string | number;
|
|
9
|
+
keys: string[];
|
|
10
|
+
}>;
|
|
11
|
+
keys?(pattern: string): Promise<string[]>;
|
|
12
|
+
quit?(): Promise<unknown>;
|
|
13
|
+
}
|
|
14
|
+
export interface RedisCacheLayerOptions {
|
|
15
|
+
id: string;
|
|
16
|
+
client: RedisCacheLayerClient;
|
|
17
|
+
ttlMs: number;
|
|
18
|
+
prefix?: string;
|
|
19
|
+
scanCount?: number;
|
|
20
|
+
closeOnShutdown?: boolean;
|
|
21
|
+
clientStyle?: 'ioredis' | 'node-redis';
|
|
22
|
+
allowBlockingClear?: boolean;
|
|
23
|
+
readTimeoutMs?: number;
|
|
24
|
+
operationTimeoutMs?: number;
|
|
25
|
+
circuitBreaker?: CacheCircuitBreakerOptions;
|
|
26
|
+
setWithTtl?: (client: RedisCacheLayerClient, key: string, value: string, ttlMs: number) => Promise<unknown>;
|
|
27
|
+
}
|
|
28
|
+
/** Redis/Valkey layer that delegates capacity and eviction to the provider. */
|
|
29
|
+
export declare function createRedisCacheLayer(options: RedisCacheLayerOptions): CacheLayer;
|
|
30
|
+
//# sourceMappingURL=redis-layer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-layer.d.ts","sourceRoot":"","sources":["../../src/cache/redis-layer.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,UAAU,EAEhB,MAAM,aAAa,CAAA;AAOpB,MAAM,WAAW,qBAAqB;IACpC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IACxC,GAAG,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAClE,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC3E,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC5C,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CACnD,CAAC,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,CAAC,GAC3B;QAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,EAAE,CAAA;KAAE,CAC9C,CAAA;IACD,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACzC,IAAI,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,qBAAqB,CAAA;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,WAAW,CAAC,EAAE,SAAS,GAAG,YAAY,CAAA;IACtC,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,cAAc,CAAC,EAAE,0BAA0B,CAAA;IAC3C,UAAU,CAAC,EAAE,CACX,MAAM,EAAE,qBAAqB,EAC7B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,KACV,OAAO,CAAC,OAAO,CAAC,CAAA;CACtB;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,GAAG,UAAU,CAuGjF"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { isCacheRecord, } from './tiered.js';
|
|
2
|
+
import { DEFAULT_CACHE_CIRCUIT_COOLDOWN_MS, DEFAULT_CACHE_CIRCUIT_FAILURE_THRESHOLD, DEFAULT_CACHE_OPERATION_TIMEOUT_MS, } from './defaults.js';
|
|
3
|
+
/** Redis/Valkey layer that delegates capacity and eviction to the provider. */
|
|
4
|
+
export function createRedisCacheLayer(options) {
|
|
5
|
+
const prefix = options.prefix ?? 'raffel:cache:';
|
|
6
|
+
const fullKey = (key) => prefix + key;
|
|
7
|
+
let hits = 0;
|
|
8
|
+
let misses = 0;
|
|
9
|
+
async function setWithNativeTtl(key, value, ttlMs) {
|
|
10
|
+
if (options.setWithTtl) {
|
|
11
|
+
await options.setWithTtl(options.client, key, value, ttlMs);
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (options.client.pSetEx) {
|
|
15
|
+
await options.client.pSetEx(key, ttlMs, value);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (!options.client.set)
|
|
19
|
+
throw new Error('Redis/Valkey client does not implement SET');
|
|
20
|
+
if (options.clientStyle === 'node-redis') {
|
|
21
|
+
await options.client.set(key, value, { PX: ttlMs });
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
await options.client.set(key, value, 'PX', ttlMs);
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
id: options.id,
|
|
28
|
+
ttlMs: options.ttlMs,
|
|
29
|
+
readTimeoutMs: options.readTimeoutMs ?? 100,
|
|
30
|
+
operationTimeoutMs: options.operationTimeoutMs ?? DEFAULT_CACHE_OPERATION_TIMEOUT_MS,
|
|
31
|
+
circuitBreaker: options.circuitBreaker ?? {
|
|
32
|
+
failureThreshold: DEFAULT_CACHE_CIRCUIT_FAILURE_THRESHOLD,
|
|
33
|
+
cooldownMs: DEFAULT_CACHE_CIRCUIT_COOLDOWN_MS,
|
|
34
|
+
},
|
|
35
|
+
async get(key) {
|
|
36
|
+
const providerKey = fullKey(key);
|
|
37
|
+
const encoded = await options.client.get(providerKey);
|
|
38
|
+
if (!encoded) {
|
|
39
|
+
misses++;
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
let record;
|
|
43
|
+
try {
|
|
44
|
+
record = JSON.parse(encoded);
|
|
45
|
+
if (!isCacheRecord(record))
|
|
46
|
+
throw new Error('Invalid cache record');
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
await options.client.del(providerKey);
|
|
50
|
+
misses++;
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
if (Date.now() >= (record.staleUntil ?? record.expiresAt)) {
|
|
54
|
+
await options.client.del(providerKey);
|
|
55
|
+
misses++;
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
hits++;
|
|
59
|
+
return record;
|
|
60
|
+
},
|
|
61
|
+
async set(key, record, ttlMs, staleMs = 0) {
|
|
62
|
+
const expiresAt = Date.now() + ttlMs;
|
|
63
|
+
const stored = {
|
|
64
|
+
...record,
|
|
65
|
+
expiresAt,
|
|
66
|
+
staleUntil: staleMs > 0 ? expiresAt + staleMs : undefined,
|
|
67
|
+
};
|
|
68
|
+
await setWithNativeTtl(fullKey(key), JSON.stringify(stored), ttlMs + staleMs);
|
|
69
|
+
},
|
|
70
|
+
async delete(key) {
|
|
71
|
+
await options.client.del(fullKey(key));
|
|
72
|
+
},
|
|
73
|
+
async clearNamespace(namespace) {
|
|
74
|
+
const pattern = `${prefix}${namespace}:*`;
|
|
75
|
+
if (!options.client.scan) {
|
|
76
|
+
if (options.allowBlockingClear && options.client.keys) {
|
|
77
|
+
const keys = await options.client.keys(pattern);
|
|
78
|
+
if (keys.length > 0)
|
|
79
|
+
await options.client.del(keys);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
throw new Error('Redis/Valkey namespace invalidation requires SCAN support');
|
|
83
|
+
}
|
|
84
|
+
let cursor = '0';
|
|
85
|
+
do {
|
|
86
|
+
const result = options.clientStyle === 'node-redis' || options.client.pSetEx
|
|
87
|
+
? await options.client.scan(cursor, {
|
|
88
|
+
MATCH: pattern,
|
|
89
|
+
COUNT: options.scanCount ?? 100,
|
|
90
|
+
})
|
|
91
|
+
: await options.client.scan(cursor, 'MATCH', pattern, 'COUNT', options.scanCount ?? 100);
|
|
92
|
+
const next = Array.isArray(result) ? result[0] : result.cursor;
|
|
93
|
+
const keys = Array.isArray(result) ? result[1] : result.keys;
|
|
94
|
+
cursor = String(next);
|
|
95
|
+
if (keys.length > 0)
|
|
96
|
+
await options.client.del(keys);
|
|
97
|
+
} while (cursor !== '0');
|
|
98
|
+
},
|
|
99
|
+
stats() {
|
|
100
|
+
return { totalItems: 0, hits, misses };
|
|
101
|
+
},
|
|
102
|
+
async shutdown() {
|
|
103
|
+
if (options.closeOnShutdown)
|
|
104
|
+
await options.client.quit?.();
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=redis-layer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis-layer.js","sourceRoot":"","sources":["../../src/cache/redis-layer.ts"],"names":[],"mappings":"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"}
|