FN-6626: close cached CLI extension task stores

Close cached TaskStore handles so CLI extension task-tool tests shut down cleanly.\n\n- Add deterministic cached-store shutdown for the CLI extension and invoke it from extension teardown.\n- Expose the shutdown helper for tests and call it after canonical-project-root task-tool cases.\n- Add a patch changeset for the published @runfusion/fusion package.\n\nFiles changed:\n .changeset/fn-6626-close-cached-stores.md             |  5 +++++\n .../cli/src/__tests__/extension-task-tools.test.ts    |  8 ++++++++\n packages/cli/src/extension.ts                         | 19 ++++++++++++++++++-\n 3 files changed, 31 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-6626

Fusion-Task-Lineage: 65791502-8992-4037-8ca0-fe21c8283506
This commit is contained in:
gsxdsm
2026-06-18 02:39:10 -07:00
parent 316968f0d3
commit 4dd533753e
3 changed files with 31 additions and 1 deletions

View File

@@ -0,0 +1,5 @@
---
"@runfusion/fusion": patch
---
Close cached CLI extension TaskStore instances on session shutdown so task-tool runs do not leave SQLite handles behind.

View File

@@ -6,6 +6,9 @@ Keep this worktree-root regression slice fast by relying on module resets and bo
FNXC:CliTests 2026-06-15-07:44: FNXC:CliTests 2026-06-15-07:44:
FN-6486 rescues this load-only timeout by closing each real TaskStore before removing its temp root and by using non-hoisted mock cleanup. The suite keeps the worktree-root regression coverage without widening timeouts, adding retries, or changing package worker settings. FN-6486 rescues this load-only timeout by closing each real TaskStore before removing its temp root and by using non-hoisted mock cleanup. The suite keeps the worktree-root regression coverage without widening timeouts, adding retries, or changing package worker settings.
FNXC:CliTests 2026-06-17-23:58:
FN-6626 requires these canonical-project-root tool tests to close the extension module's cached TaskStore instances after every case, because fixture-store cleanup alone does not close the second store opened by fn_task_show/fn_task_list.
*/ */
import { mkdtemp, mkdir, rm, writeFile } from "node:fs/promises"; import { mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os"; import { tmpdir } from "node:os";
@@ -17,8 +20,11 @@ function makeCtx(cwd: string) {
return { cwd } as any; return { cwd } as any;
} }
let closeLoadedExtensionStores: (() => void) | undefined;
async function loadExtension() { async function loadExtension() {
const mod = await import("../extension.js"); const mod = await import("../extension.js");
closeLoadedExtensionStores = mod.closeCachedStores;
return mod.default; return mod.default;
} }
@@ -32,6 +38,8 @@ describe("extension task tools resolve repo root from worktrees", () => {
}); });
afterEach(() => { afterEach(() => {
closeLoadedExtensionStores?.();
closeLoadedExtensionStores = undefined;
vi.restoreAllMocks(); vi.restoreAllMocks();
vi.doUnmock("@fusion/core"); vi.doUnmock("@fusion/core");
}); });

View File

@@ -152,6 +152,23 @@ async function getStore(cwd: string): Promise<TaskStore> {
return store; return store;
} }
/** @internal Exposed so tests and the extension shutdown hook can close cached stores deterministically; not a public CLI API contract. */
export function closeCachedStores(): void {
/*
FNXC:CliTests 2026-06-17-23:58:
FN-6626 found the CLI extension cache cleared real TaskStore instances without closing them, leaving SQLite/WAL handles to survive module resets and making canonical-project-root task-tool tests timeout under suite load.
Close every cached store deterministically on extension shutdown and in tests; do not appease the load-sensitive seam with timeouts, retries, or worker changes.
*/
for (const store of storeCache.values()) {
try {
store.close();
} catch (error) {
console.warn("[fusion-extension] cached TaskStore close skipped", error);
}
}
storeCache.clear();
}
function getFusionDir(cwd: string): string { function getFusionDir(cwd: string): string {
return join(resolveProjectRoot(cwd), ".fusion"); return join(resolveProjectRoot(cwd), ".fusion");
} }
@@ -4572,6 +4589,6 @@ export default function kbExtension(pi: ExtensionAPI) {
dashboardProcess = null; dashboardProcess = null;
dashboardPort = null; dashboardPort = null;
} }
storeCache.clear(); closeCachedStores();
}); });
} }