

















@@ -32,6 +32,7 @@ let embedBatchInputCalls = 0;
3232let providerCloseCalls = 0;
3333let providerCloseFailuresRemaining = 0;
3434let providerCloseGate: Promise<void> | null = null;
35+let providerInitGate: Promise<void> | null = null;
3536let providerCalls: Array<{ provider?: string; model?: string; outputDimensionality?: number }> = [];
3637let forceNoProvider = false;
3738@@ -67,6 +68,7 @@ vi.mock("./embeddings.js", () => {
6768model: options.model,
6869outputDimensionality: options.outputDimensionality,
6970});
71+await providerInitGate;
7072if (forceNoProvider) {
7173return {
7274provider: null,
@@ -218,6 +220,7 @@ describe("memory index", () => {
218220providerCloseCalls = 0;
219221providerCloseFailuresRemaining = 0;
220222providerCloseGate = null;
223+providerInitGate = null;
221224providerCalls = [];
222225forceNoProvider = false;
223226@@ -402,7 +405,7 @@ describe("memory index", () => {
402405expect(providerCloseCalls).toBe(1);
403406});
404407405-it("closes embedding providers before waiting for pending sync to settle", async () => {
408+it("waits for pending sync before closing embedding providers", async () => {
406409const cfg = createCfg({
407410storePath: indexMainPath,
408411hybrid: { enabled: true, vectorWeight: 0.5, textWeight: 0.5 },
@@ -415,18 +418,77 @@ describe("memory index", () => {
415418});
416419417420const closePromise = manager.close();
418-await vi.waitFor(() => {
419-expect(providerCloseCalls).toBe(1);
421+try {
422+await Promise.resolve();
423+expect(providerCloseCalls).toBe(0);
424+425+let closeSettled = false;
426+void closePromise.then(() => {
427+closeSettled = true;
428+});
429+await Promise.resolve();
430+431+expect(closeSettled).toBe(false);
432+} finally {
433+resolveSync();
434+}
435+await closePromise;
436+expect(providerCloseCalls).toBe(1);
437+});
438+439+it("waits for sync that attaches after provider initialization before closing providers", async () => {
440+let releaseProviderInit: () => void = () => {};
441+providerInitGate = new Promise<void>((resolve) => {
442+releaseProviderInit = resolve;
420443});
421-let closeSettled = false;
422-void closePromise.then(() => {
423-closeSettled = true;
444+const cfg = createCfg({
445+storePath: indexMainPath,
446+hybrid: { enabled: true, vectorWeight: 0.5, textWeight: 0.5 },
447+});
448+const manager = await getFreshManager(cfg);
449+let releaseSync: () => void = () => {};
450+const syncStarted = new Promise<void>((resolve) => {
451+const originalRunSyncWithReadonlyRecovery = (
452+manager as unknown as {
453+runSyncWithReadonlyRecovery: (params?: {
454+reason?: string;
455+force?: boolean;
456+sessionFiles?: string[];
457+progress?: (update: unknown) => void;
458+}) => Promise<void>;
459+}
460+).runSyncWithReadonlyRecovery.bind(manager);
461+(
462+manager as unknown as {
463+runSyncWithReadonlyRecovery: typeof originalRunSyncWithReadonlyRecovery;
464+}
465+).runSyncWithReadonlyRecovery = async (params) => {
466+resolve();
467+await new Promise<void>((syncResolve) => {
468+releaseSync = syncResolve;
469+});
470+await originalRunSyncWithReadonlyRecovery(params);
471+};
424472});
425-await Promise.resolve();
426473427-expect(closeSettled).toBe(false);
428-resolveSync();
474+const syncPromise = manager.sync({ reason: "test" });
475+await vi.waitFor(() => {
476+expect(providerCalls).toHaveLength(1);
477+});
478+479+const closePromise = manager.close();
480+try {
481+releaseProviderInit();
482+await syncStarted;
483+await Promise.resolve();
484+485+expect(providerCloseCalls).toBe(0);
486+} finally {
487+releaseSync();
488+}
489+await syncPromise;
429490await closePromise;
491+expect(providerCloseCalls).toBe(1);
430492});
431493432494it("evicts scoped memory index managers before close settles", async () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。