Skip to content

Commit a103a2c

Browse files
authored
Merge branch 'main' into feat/386-request-deduplication
2 parents 393dec0 + bb5bda7 commit a103a2c

25 files changed

Lines changed: 1316 additions & 61 deletions

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@
1818
"types": "./dist/testing/index.d.ts",
1919
"import": "./dist/testing/index.js",
2020
"require": "./dist/testing/index.cjs"
21+
},
22+
"./utils": {
23+
"types": "./dist/utils.d.ts",
24+
"import": "./dist/utils.js",
25+
"require": "./dist/utils.cjs"
2126
}
2227
},
2328
"files": [

src/cache.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface CacheStats {
1010
misses: number;
1111
size: number;
1212
keys: string[];
13+
evictions: number;
1314
}
1415

1516
export interface MethodCacheEntry {
@@ -23,9 +24,12 @@ export class SimpleCache<T> {
2324
private enabled: boolean;
2425
private hits = 0;
2526
private misses = 0;
27+
private evictions = 0;
28+
private maxEntries: number;
2629

27-
constructor(config?: { enabled?: boolean; ttl?: Record<string, number>; ttlMs?: number }) {
28-
this.enabled = config?.enabled ?? (config?.ttl ? true : false) ?? (config?.ttlMs !== undefined ? true : false);
30+
constructor(config?: { enabled?: boolean; ttl?: Record<string, number>; ttlMs?: number; maxEntries?: number }) {
31+
this.enabled = config?.enabled ?? (config?.ttl !== undefined || config?.ttlMs !== undefined);
32+
this.maxEntries = config?.maxEntries ?? (this.enabled ? 1000 : 0);
2933
this.ttlConfig = config?.ttl ?? {};
3034
if (config?.ttlMs !== undefined) {
3135
this.ttlConfig["default"] = config.ttlMs;
@@ -44,6 +48,11 @@ export class SimpleCache<T> {
4448
this.misses++;
4549
return undefined;
4650
}
51+
52+
// Update LRU order
53+
this.store.delete(key);
54+
this.store.set(key, entry);
55+
4756
this.hits++;
4857
return entry.value;
4958
}
@@ -53,6 +62,15 @@ export class SimpleCache<T> {
5362
const method = key.split(":")[0] || key;
5463
const ttl = this.ttlConfig[method] ?? this.ttlConfig["default"] ?? 0;
5564
if (ttl <= 0) return;
65+
66+
if (this.maxEntries > 0 && this.store.size >= this.maxEntries && !this.store.has(key)) {
67+
const oldestKey = this.store.keys().next().value;
68+
if (oldestKey !== undefined) {
69+
this.store.delete(oldestKey);
70+
this.evictions++;
71+
}
72+
}
73+
5674
this.store.set(key, { value, expiresAt: Date.now() + ttl });
5775
}
5876

@@ -97,6 +115,7 @@ export class SimpleCache<T> {
97115
misses: this.misses,
98116
size: this.store.size,
99117
keys: Array.from(this.store.keys()),
118+
evictions: this.evictions,
100119
};
101120
}
102121

0 commit comments

Comments
 (0)