mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-07 02:58:02 +00:00
fix(fts): try local LOAD before INSTALL to avoid network failures (#726)
Some checks are pending
CI / quality (push) Waiting to run
CI / tests (push) Waiting to run
CI / e2e (push) Waiting to run
CI / scope-parity (push) Waiting to run
CI / Save PR Metadata (push) Blocked by required conditions
CI / CI Gate (push) Blocked by required conditions
Release Candidate / ci (push) Blocked by required conditions
Release Candidate / Publish release candidate to npm (push) Blocked by required conditions
Release Candidate / Build & Push RC Docker images (push) Blocked by required conditions
Release Candidate / Check if release candidate should run (push) Waiting to run
Some checks are pending
CI / quality (push) Waiting to run
CI / tests (push) Waiting to run
CI / e2e (push) Waiting to run
CI / scope-parity (push) Waiting to run
CI / Save PR Metadata (push) Blocked by required conditions
CI / CI Gate (push) Blocked by required conditions
Release Candidate / ci (push) Blocked by required conditions
Release Candidate / Publish release candidate to npm (push) Blocked by required conditions
Release Candidate / Build & Push RC Docker images (push) Blocked by required conditions
Release Candidate / Check if release candidate should run (push) Waiting to run
This commit is contained in:
parent
2d7b15f18c
commit
3eeb2833e4
3 changed files with 57 additions and 24 deletions
|
|
@ -1144,23 +1144,40 @@ export const getEmbeddingTableName = (): string => EMBEDDING_TABLE_NAME;
|
|||
|
||||
/**
|
||||
* Load the FTS extension (required before using FTS functions).
|
||||
* Safe to call multiple times — tracks loaded state via module-level ftsLoaded.
|
||||
*
|
||||
* Safe to call multiple times — when invoked without arguments, tracks loaded
|
||||
* state via module-level `ftsLoaded`. When invoked with an explicit
|
||||
* connection, loads on that connection and returns whether the load
|
||||
* succeeded — letting callers (e.g. the pool adapter) track their own state.
|
||||
*
|
||||
* Tries `LOAD EXTENSION fts` first so previously-cached installs skip the
|
||||
* network entirely; falls back to `INSTALL` + `LOAD` only when the extension
|
||||
* hasn't been cached yet.
|
||||
*/
|
||||
export const loadFTSExtension = async (): Promise<void> => {
|
||||
if (ftsLoaded) return;
|
||||
if (!conn) {
|
||||
export const loadFTSExtension = async (targetConn?: lbug.Connection): Promise<boolean> => {
|
||||
const useModuleState = targetConn === undefined;
|
||||
if (useModuleState && ftsLoaded) return true;
|
||||
|
||||
const c: lbug.Connection | null = targetConn ?? conn;
|
||||
if (!c) {
|
||||
throw new Error('LadybugDB not initialized. Call initLbug first.');
|
||||
}
|
||||
|
||||
const markLoaded = (): true => {
|
||||
if (useModuleState) ftsLoaded = true;
|
||||
return true;
|
||||
};
|
||||
|
||||
try {
|
||||
// Try loading locally first (no network required)
|
||||
await conn.query('LOAD EXTENSION fts');
|
||||
ftsLoaded = true;
|
||||
await c.query('LOAD EXTENSION fts');
|
||||
return markLoaded();
|
||||
} catch {
|
||||
// Fall back to install + load (requires network)
|
||||
try {
|
||||
await conn.query('INSTALL fts');
|
||||
await conn.query('LOAD EXTENSION fts');
|
||||
ftsLoaded = true;
|
||||
await c.query('INSTALL fts');
|
||||
await c.query('LOAD EXTENSION fts');
|
||||
return markLoaded();
|
||||
} catch (err: any) {
|
||||
const msg = err?.message || '';
|
||||
if (
|
||||
|
|
@ -1168,10 +1185,10 @@ export const loadFTSExtension = async (): Promise<void> => {
|
|||
msg.includes('already installed') ||
|
||||
msg.includes('already exists')
|
||||
) {
|
||||
ftsLoaded = true;
|
||||
} else {
|
||||
console.error('GitNexus: FTS extension load failed:', msg);
|
||||
return markLoaded();
|
||||
}
|
||||
console.error('GitNexus: FTS extension load failed:', msg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
import fs from 'fs/promises';
|
||||
import lbug from '@ladybugdb/core';
|
||||
import { loadFTSExtension } from './lbug-adapter.js';
|
||||
|
||||
/** Per-repo pool: one Database, many Connections */
|
||||
interface PoolEntry {
|
||||
|
|
@ -354,12 +355,7 @@ async function doInitLbug(repoId: string, dbPath: string): Promise<void> {
|
|||
// Done BEFORE pool registration so no concurrent checkout can grab
|
||||
// the connection while the async FTS load is in progress.
|
||||
if (!shared.ftsLoaded) {
|
||||
try {
|
||||
await available[0].query('LOAD EXTENSION fts');
|
||||
shared.ftsLoaded = true;
|
||||
} catch {
|
||||
// Extension may not be installed — FTS queries will fail gracefully
|
||||
}
|
||||
shared.ftsLoaded = await loadFTSExtension(available[0]);
|
||||
}
|
||||
|
||||
// Load VECTOR extension once per shared Database for semantic search support.
|
||||
|
|
@ -433,12 +429,7 @@ export async function initLbugWithDb(
|
|||
|
||||
// Load FTS extension if not already loaded on this Database
|
||||
if (!shared.ftsLoaded) {
|
||||
try {
|
||||
await available[0].query('LOAD EXTENSION fts');
|
||||
shared.ftsLoaded = true;
|
||||
} catch {
|
||||
// Extension may already be loaded or not installed
|
||||
}
|
||||
shared.ftsLoaded = await loadFTSExtension(available[0]);
|
||||
}
|
||||
|
||||
// Load VECTOR extension for semantic search support
|
||||
|
|
|
|||
|
|
@ -45,6 +45,31 @@ withTestLbugDB(
|
|||
).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
it('loadFTSExtension(conn): loads on an explicit connection and returns true', async () => {
|
||||
const lbug = (await import('@ladybugdb/core')).default;
|
||||
const { loadFTSExtension, getDatabase } =
|
||||
await import('../../src/core/lbug/lbug-adapter.js');
|
||||
|
||||
const db = getDatabase();
|
||||
expect(db).not.toBeNull();
|
||||
|
||||
// Fresh Connection on the same Database — simulates the pool adapter's
|
||||
// path where loadFTSExtension is called with an explicit connection
|
||||
// rather than the module-level singleton.
|
||||
const freshConn = new lbug.Connection(db!);
|
||||
try {
|
||||
const loaded = await loadFTSExtension(freshConn);
|
||||
expect(loaded).toBe(true);
|
||||
|
||||
// Idempotent on the same connection — calling again still returns true
|
||||
// (exercises the "already loaded" catch branch in the fallback path).
|
||||
const loadedAgain = await loadFTSExtension(freshConn);
|
||||
expect(loadedAgain).toBe(true);
|
||||
} finally {
|
||||
await freshConn.close().catch(() => {});
|
||||
}
|
||||
});
|
||||
|
||||
it('getLbugStats: returns correct node and edge counts for seeded data', async () => {
|
||||
const { getLbugStats } = await import('../../src/core/lbug/lbug-adapter.js');
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue