fix: verify sqlite-vec readiness after extension load. Closes #169
This commit is contained in:
parent
96643a28ed
commit
73136e4f59
@ -8,6 +8,7 @@
|
||||
|
||||
import { describe, test, expect, beforeAll, afterAll, beforeEach, afterEach, mock, spyOn } from "bun:test";
|
||||
import { Database } from "bun:sqlite";
|
||||
import * as sqliteVec from "sqlite-vec";
|
||||
import { unlink, mkdtemp, rmdir, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
@ -15,6 +16,7 @@ import YAML from "yaml";
|
||||
import { disposeDefaultLlamaCpp } from "./llm.js";
|
||||
import {
|
||||
createStore,
|
||||
verifySqliteVecLoaded,
|
||||
getDefaultDbPath,
|
||||
homedir,
|
||||
resolve,
|
||||
@ -452,6 +454,25 @@ describe("Store Creation", () => {
|
||||
await cleanupTestDb(store);
|
||||
});
|
||||
|
||||
test("verifySqliteVecLoaded throws when sqlite-vec is not loaded", () => {
|
||||
const db = new Database(":memory:");
|
||||
try {
|
||||
expect(() => verifySqliteVecLoaded(db)).toThrow("sqlite-vec extension is unavailable");
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("verifySqliteVecLoaded succeeds when sqlite-vec is loaded", () => {
|
||||
const db = new Database(":memory:");
|
||||
try {
|
||||
sqliteVec.load(db);
|
||||
expect(() => verifySqliteVecLoaded(db)).not.toThrow();
|
||||
} finally {
|
||||
db.close();
|
||||
}
|
||||
});
|
||||
|
||||
test("store.close closes the database connection", async () => {
|
||||
const store = await createTestStore();
|
||||
store.close();
|
||||
|
||||
41
src/store.ts
41
src/store.ts
@ -458,17 +458,46 @@ function setSQLiteFromBrewPrefixEnv(): void {
|
||||
|
||||
setSQLiteFromBrewPrefixEnv();
|
||||
|
||||
function createSqliteVecUnavailableError(reason: string): Error {
|
||||
return new Error(
|
||||
"sqlite-vec extension is unavailable. " +
|
||||
`${reason}. ` +
|
||||
"Install Homebrew SQLite so the sqlite-vec extension can be loaded, " +
|
||||
"and set BREW_PREFIX if Homebrew is installed in a non-standard location."
|
||||
);
|
||||
}
|
||||
|
||||
function getErrorMessage(err: unknown): string {
|
||||
return err instanceof Error ? err.message : String(err);
|
||||
}
|
||||
|
||||
export function verifySqliteVecLoaded(db: Database): void {
|
||||
try {
|
||||
const row = db.prepare(`SELECT vec_version() AS version`).get() as { version?: string } | null;
|
||||
if (!row?.version || typeof row.version !== "string") {
|
||||
throw new Error("vec_version() returned no version");
|
||||
}
|
||||
} catch (err) {
|
||||
const message = getErrorMessage(err);
|
||||
throw createSqliteVecUnavailableError(`sqlite-vec probe failed (${message})`);
|
||||
}
|
||||
}
|
||||
|
||||
function initializeDatabase(db: Database): void {
|
||||
try {
|
||||
sqliteVec.load(db);
|
||||
verifySqliteVecLoaded(db);
|
||||
} catch (err) {
|
||||
if (err instanceof Error && err.message.includes("does not support dynamic extension loading")) {
|
||||
throw new Error(
|
||||
"SQLite build does not support dynamic extension loading. " +
|
||||
"Install Homebrew SQLite so the sqlite-vec extension can be loaded, " +
|
||||
"and set BREW_PREFIX if Homebrew is installed in a non-standard location."
|
||||
);
|
||||
const message = getErrorMessage(err);
|
||||
|
||||
if (message.includes("does not support dynamic extension loading")) {
|
||||
throw createSqliteVecUnavailableError("SQLite build does not support dynamic extension loading");
|
||||
}
|
||||
|
||||
if (message.includes("sqlite-vec extension is unavailable")) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
db.exec("PRAGMA journal_mode = WAL");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user