Skip to content

Commit a021efb

Browse files
shakkernerdjalehman
authored andcommitted
fix: keep source-wide batch fallback aligned
1 parent 5f6fc02 commit a021efb

2 files changed

Lines changed: 41 additions & 1 deletion

File tree

extensions/memory-core/src/memory/index.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ let embedBatchCalls = 0;
3131
let embedBatchInputCalls = 0;
3232
let providerRuntimeBatchCalls: string[][] = [];
3333
let providerRuntimeBatchGate: Promise<void> | null = null;
34+
let providerRuntimeBatchFailuresRemaining = 0;
3435
let providerRuntimeActiveBatchCalls = 0;
3536
let providerRuntimeMaxActiveBatchCalls = 0;
3637
let providerCloseCalls = 0;
@@ -162,6 +163,10 @@ vi.mock("./embeddings.js", () => {
162163
try {
163164
await providerRuntimeBatchGate;
164165
providerRuntimeBatchCalls.push(batch.chunks.map((chunk) => chunk.text));
166+
if (providerRuntimeBatchFailuresRemaining > 0) {
167+
providerRuntimeBatchFailuresRemaining -= 1;
168+
throw new Error("provider runtime batch failed");
169+
}
165170
return batch.chunks.map((chunk) => embedText(chunk.text));
166171
} finally {
167172
providerRuntimeActiveBatchCalls -= 1;
@@ -251,6 +256,7 @@ describe("memory index", () => {
251256
embedBatchInputCalls = 0;
252257
providerRuntimeBatchCalls = [];
253258
providerRuntimeBatchGate = null;
259+
providerRuntimeBatchFailuresRemaining = 0;
254260
providerRuntimeActiveBatchCalls = 0;
255261
providerRuntimeMaxActiveBatchCalls = 0;
256262
providerCloseCalls = 0;
@@ -481,6 +487,40 @@ describe("memory index", () => {
481487
}
482488
});
483489

490+
it("maps source-wide batch fallback results to missing chunks after cache hits", async () => {
491+
const cfg = createCfg({
492+
provider: "batch-wide-test",
493+
batchEnabled: true,
494+
storePath: path.join(workspaceDir, "index-cross-file-batch-fallback-cache.sqlite"),
495+
});
496+
const manager = await getFreshManager(cfg);
497+
try {
498+
await manager.sync({ reason: "test" });
499+
500+
await fs.writeFile(path.join(memoryDir, "2026-01-13.md"), "# Log\nBeta memory line.");
501+
providerRuntimeBatchCalls = [];
502+
providerRuntimeBatchFailuresRemaining = 1;
503+
embedBatchCalls = 0;
504+
505+
await manager.sync({ reason: "test", force: true });
506+
507+
expect(providerRuntimeBatchCalls).toEqual([["# Log\nBeta memory line."]]);
508+
expect(embedBatchCalls).toBe(1);
509+
const betaRow = (
510+
manager as unknown as {
511+
db: { prepare: (sql: string) => { get: (...args: unknown[]) => unknown } };
512+
}
513+
).db
514+
.prepare("SELECT embedding FROM chunks WHERE path LIKE ? AND source = ?")
515+
.get("%2026-01-13.md", "memory") as { embedding: string } | undefined;
516+
517+
expect(betaRow).toBeDefined();
518+
expect(JSON.parse(betaRow?.embedding ?? "[]")).toEqual([0, 1, 0, 0]);
519+
} finally {
520+
await manager.close?.();
521+
}
522+
});
523+
484524
it("splits oversized source-wide embedding requests at the request cap", () => {
485525
expect(splitSourceWideEmbeddingChunks(["one", "two", "three", "four", "five"], 2)).toEqual([
486526
["one", "two"],

extensions/memory-core/src/memory/manager-embedding-ops.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ export abstract class MemoryManagerEmbeddingOps extends MemoryManagerSyncOps {
334334
timeoutMs: this.batch.timeoutMs,
335335
debug: this.buildBatchDebug(source, chunks, debugContext),
336336
}),
337-
fallback: async () => await this.embedChunksInBatches(chunks),
337+
fallback: async () => await this.embedChunksInBatches(missingChunks),
338338
});
339339
if (!batchResult) {
340340
return this.embedChunksInBatches(chunks);

0 commit comments

Comments
 (0)