refactor(fts): pool adapter calls loadFTSExtension, drop debug breadcrumb

Addresses PR #726 review feedback.

- pool-adapter.ts now calls loadFTSExtension(available[0]) in both
  initPool and initLbugWithDb instead of duplicating the LOAD/INSTALL
  try-catch chain.
- loadFTSExtension accepts an optional connection and returns a boolean
  so the pool adapter can track shared.ftsLoaded without replicating
  the error handling.
- Removed the console.debug breadcrumb per reviewer request.
This commit is contained in:
Pratyush Sharma 2026-04-24 00:48:01 +05:30
parent 81458a2be8
commit 7ee2b9b54a
No known key found for this signature in database
2 changed files with 36 additions and 47 deletions

View file

@ -1144,29 +1144,41 @@ 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) {
throw new Error('LadybugDB not initialized. Call initLbug first.');
export const loadFTSExtension = async (targetConn?: lbug.Connection): Promise<boolean> => {
const useModuleState = targetConn === undefined;
if (useModuleState) {
if (ftsLoaded) return true;
if (!conn) {
throw new Error('LadybugDB not initialized. Call initLbug first.');
}
targetConn = conn;
}
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;
} catch (err: any) {
// Fall back to install + load (requires network). Log a breadcrumb so
// cache corruption / version mismatches leave a diagnostic trail instead
// of a silent fall-through to the (slower, network-bound) INSTALL path.
console.debug(
'GitNexus: FTS LOAD from cache failed, will attempt INSTALL:',
err?.message || '',
);
await targetConn!.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 targetConn!.query('INSTALL fts');
await targetConn!.query('LOAD EXTENSION fts');
return markLoaded();
} catch (err: any) {
const msg = err?.message || '';
if (
@ -1174,10 +1186,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;
}
}
};

View file

@ -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,19 +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 not cached locally — try INSTALL (downloads from remote) then LOAD
try {
await available[0].query('INSTALL fts');
await available[0].query('LOAD EXTENSION fts');
shared.ftsLoaded = true;
} catch {
// FTS unavailable — queries will fail gracefully
}
}
shared.ftsLoaded = await loadFTSExtension(available[0]);
}
// Load VECTOR extension once per shared Database for semantic search support.
@ -440,19 +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 not cached locally — try INSTALL (downloads from remote) then LOAD
try {
await available[0].query('INSTALL fts');
await available[0].query('LOAD EXTENSION fts');
shared.ftsLoaded = true;
} catch {
// FTS unavailable — queries will fail gracefully
}
}
shared.ftsLoaded = await loadFTSExtension(available[0]);
}
// Load VECTOR extension for semantic search support