Skip to content

Commit 17556ba

Browse files
committed
fix(embedder): update LRU insertion order when re-setting existing key
Issue #598 Phase 3: When an existing cache key is re-set, explicitly delete it first to maintain correct LRU ordering. Without this, the insertion order stays stale and the LRU eviction removes the wrong entry. Also adds unit test for LRU semantics.
1 parent 619d703 commit 17556ba

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

src/embedder.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ class EmbeddingCache {
6969

7070
set(text: string, task: string | undefined, vector: number[]): void {
7171
const k = this.key(text, task);
72+
// If key already exists, delete to update insertion order for correct LRU semantics
73+
if (this.cache.has(k)) {
74+
this.cache.delete(k);
75+
}
7276
// When cache is full, run TTL eviction first (removes expired + oldest).
7377
// This prevents unbounded growth from stale entries while keeping writes O(1).
7478
if (this.cache.size >= this.maxSize) {

test/embedder-lru.test.mjs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Issue #598 Phase 3 - EmbeddingCache LRU Semantics Test
3+
* Tests that re-setting an existing key updates its LRU position.
4+
*/
5+
6+
import { describe, it } from "node:test";
7+
import assert from "node:assert";
8+
9+
const jiti = require("jiti")(__filename);
10+
11+
describe("EmbeddingCache LRU semantics", () => {
12+
it("updates insertion order when re-setting existing key", async () => {
13+
const { Embedder } = jiti("../src/embedder.ts");
14+
15+
const embedder = new Embedder({});
16+
const cache = embedder["cache"];
17+
18+
// Set two keys
19+
cache.set("key1", undefined, [1, 0, 0]);
20+
cache.set("key2", undefined, [0, 1, 0]);
21+
22+
// Re-set key1 with different value (should move to most recent)
23+
cache.set("key1", undefined, [1, 1, 0]);
24+
25+
// Evict one - should evict key2 (oldest), not key1 (which was re-set)
26+
cache.set("key3", undefined, [0, 0, 1]);
27+
28+
assert.strictEqual(cache.cache.has("key1"), true, "key1 should remain after re-set");
29+
assert.strictEqual(cache.cache.has("key2"), false, "key2 should be evicted (oldest)");
30+
assert.strictEqual(cache.cache.has("key3"), true, "key3 should be added");
31+
});
32+
});

0 commit comments

Comments
 (0)