mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-11 03:38:07 +00:00
fix(lbug): lock queryImporters against the WAL driver (#2264)
queryImporters issued a raw conn.query on the singleton connection inside the importer-BFS loop of incremental --pdg writeback, while the WAL-checkpoint driver could fire a concurrent CHECKPOINT — the same double-free class. Wrap the read (query + getAll + drain) in withConnLock. Extends lbug-conn-serialization.test.ts with a routing assertion. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JBJomjoTdBV2eveDVq4JMm
This commit is contained in:
parent
775059912d
commit
071b120169
2 changed files with 29 additions and 16 deletions
|
|
@ -2003,7 +2003,8 @@ export const getEmbeddingTableName = (): string => EMBEDDING_TABLE_NAME;
|
|||
* exports.
|
||||
*/
|
||||
export const queryImporters = async (targetFilePath: string): Promise<string[]> => {
|
||||
if (!conn) {
|
||||
const c = conn;
|
||||
if (!c) {
|
||||
throw new Error('LadybugDB not initialized. Call initLbug first.');
|
||||
}
|
||||
const escaped = targetFilePath.replace(/'/g, "''");
|
||||
|
|
@ -2012,22 +2013,27 @@ export const queryImporters = async (targetFilePath: string): Promise<string[]>
|
|||
WHERE r.type = 'IMPORTS' AND b.filePath = '${escaped}'
|
||||
RETURN DISTINCT a.filePath AS importer
|
||||
`;
|
||||
let queryResult: lbug.QueryResult | lbug.QueryResult[] | undefined;
|
||||
try {
|
||||
queryResult = await conn.query(cypher);
|
||||
const result = Array.isArray(queryResult) ? queryResult[0] : queryResult;
|
||||
const rows = await result.getAll();
|
||||
const out: string[] = [];
|
||||
for (const row of rows) {
|
||||
const v = (row as { importer?: unknown }).importer;
|
||||
if (typeof v === 'string' && v.length > 0) out.push(v);
|
||||
// Runs inside the connection lock: queryImporters is called in the importer-BFS
|
||||
// loop during incremental --pdg writeback while the WAL driver is live, so an
|
||||
// unlocked conn.query here could race a concurrent CHECKPOINT on the singleton.
|
||||
return withConnLock(async () => {
|
||||
let queryResult: lbug.QueryResult | lbug.QueryResult[] | undefined;
|
||||
try {
|
||||
queryResult = await c.query(cypher);
|
||||
const result = Array.isArray(queryResult) ? queryResult[0] : queryResult;
|
||||
const rows = await result.getAll();
|
||||
const out: string[] = [];
|
||||
for (const row of rows) {
|
||||
const v = (row as { importer?: unknown }).importer;
|
||||
if (typeof v === 'string' && v.length > 0) out.push(v);
|
||||
}
|
||||
return out;
|
||||
} catch {
|
||||
return [];
|
||||
} finally {
|
||||
if (queryResult) await closeQueryResults(queryResult);
|
||||
}
|
||||
return out;
|
||||
} catch {
|
||||
return [];
|
||||
} finally {
|
||||
if (queryResult) await closeQueryResults(queryResult);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -41,5 +41,12 @@ withTestLbugDB('conn-serialization', () => {
|
|||
expect(lockSpy).toHaveBeenCalled();
|
||||
expect(result).toMatchObject({ nodesDeleted: 0 });
|
||||
});
|
||||
|
||||
it('U2: queryImporters routes through withConnLock', async () => {
|
||||
const { queryImporters } = await import('../../src/core/lbug/lbug-adapter.js');
|
||||
const importers = await queryImporters('any/path.ts');
|
||||
expect(lockSpy).toHaveBeenCalled();
|
||||
expect(importers).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue