Skip to content

Commit 8a6c7fb

Browse files
committed
fix: query-do explain/metrics + local-executor file handle leak
query-do.ts: - fragmentsSkipped used dataset.fragmentMetas.size instead of allFragments.length when partition catalog active — inflated count by including fragments already pruned by catalog - explain() reported meta.totalRows as estimatedRows, ignoring fragment-level pruning — now uses estimatedRowsAfterPrune local-executor.ts: - readPage() didn't close file handle on I/O error — handle leaked until process exit. Now closes handle in catch block so subsequent calls re-open cleanly.
1 parent 606e5d0 commit 8a6c7fb

2 files changed

Lines changed: 10 additions & 7 deletions

File tree

src/local-executor.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -310,9 +310,14 @@ export class LocalExecutor implements QueryExecutor {
310310
columns: projectedColumns,
311311
async readPage(_col: ColumnMeta, page: PageInfo): Promise<ArrayBuffer> {
312312
if (!cachedHandle) cachedHandle = await fsMod.open(table, "r");
313-
const buf = Buffer.alloc(page.byteLength);
314-
await cachedHandle.read(buf, 0, page.byteLength, Number(page.byteOffset));
315-
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
313+
try {
314+
const buf = Buffer.alloc(page.byteLength);
315+
await cachedHandle.read(buf, 0, page.byteLength, Number(page.byteOffset));
316+
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
317+
} catch (err) {
318+
if (cachedHandle) { await cachedHandle.close().catch(() => {}); cachedHandle = null; }
319+
throw err;
320+
}
316321
},
317322
async close(): Promise<void> {
318323
if (cachedHandle) { await cachedHandle.close(); cachedHandle = null; }

src/query-do.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@ export class QueryDO extends DurableObject<Env> {
763763
pagesScanned: pagesTotal - pagesSkipped,
764764
estimatedBytes,
765765
estimatedR2Reads: coalesced.length,
766-
estimatedRows: meta.totalRows,
766+
estimatedRows: estimatedRowsAfterPrune,
767767
fragments: totalFragments,
768768
fragmentsSkipped,
769769
fragmentsScanned,
@@ -1694,9 +1694,7 @@ export class QueryDO extends DurableObject<Env> {
16941694
const fragments = allFragments.filter(meta =>
16951695
!canSkipFragment(meta, query.filters, query.filterGroups),
16961696
);
1697-
const fragmentsSkipped = (candidateFragmentIds
1698-
? dataset.fragmentMetas.size
1699-
: allFragments.length) - fragments.length;
1697+
const fragmentsSkipped = allFragments.length - fragments.length;
17001698
if (fragmentsSkipped > 0) {
17011699
this.log("info", "fragment_prune", {
17021700
total: allFragments.length, skipped: fragmentsSkipped, remaining: fragments.length,

0 commit comments

Comments
 (0)