@@ -20,6 +20,14 @@ import { QueryModeError } from "./errors.js";
2020import { parseLanceV2Columns , lanceV2ToColumnMeta , computeLanceV2Stats } from "./lance-v2.js" ;
2121import { buildPipeline , drainPipeline , DEFAULT_MEMORY_BUDGET , buildKeptPageIndices , type FragmentSource , type PipelineOptions } from "./operators.js" ;
2222
23+ /** Evict oldest entry from a Map when it exceeds maxSize. */
24+ function evictOldest < K , V > ( cache : Map < K , V > , maxSize : number ) : void {
25+ if ( cache . size > maxSize ) {
26+ const firstKey = cache . keys ( ) . next ( ) . value ;
27+ if ( firstKey !== undefined ) cache . delete ( firstKey ) ;
28+ }
29+ }
30+
2331/**
2432 * Executor for local mode (Node/Bun).
2533 * Reads Lance/Parquet files directly from the filesystem or via HTTP.
@@ -335,10 +343,7 @@ export class LocalExecutor implements QueryExecutor {
335343 }
336344 cached = isUrl ? await this . loadMetaFromUrl ( table ) : await this . loadMetaFromFile ( table ) ;
337345 this . metaCache . set ( table , cached ) ;
338- if ( this . metaCache . size > 1000 ) {
339- const firstKey = this . metaCache . keys ( ) . next ( ) . value ;
340- if ( firstKey ) this . metaCache . delete ( firstKey ) ;
341- }
346+ evictOldest ( this . metaCache , 1000 ) ;
342347 return cached ;
343348 }
344349
@@ -374,10 +379,7 @@ export class LocalExecutor implements QueryExecutor {
374379 ? await this . loadMetaFromUrl ( query . table )
375380 : await this . loadMetaFromFile ( query . table ) ;
376381 this . metaCache . set ( query . table , meta ) ;
377- if ( this . metaCache . size > 1000 ) {
378- const firstKey = this . metaCache . keys ( ) . next ( ) . value ;
379- if ( firstKey ) this . metaCache . delete ( firstKey ) ;
380- }
382+ evictOldest ( this . metaCache , 1000 ) ;
381383 }
382384 const metaMs = Date . now ( ) - metaStart ;
383385
@@ -805,10 +807,7 @@ export class LocalExecutor implements QueryExecutor {
805807 updatedAt : Date . now ( ) ,
806808 } ;
807809 this . datasetCache . set ( cacheKey , dataset ) ;
808- if ( this . datasetCache . size > 100 ) {
809- const firstKey = this . datasetCache . keys ( ) . next ( ) . value ;
810- if ( firstKey ) this . datasetCache . delete ( firstKey ) ;
811- }
810+ evictOldest ( this . datasetCache , 100 ) ;
812811 return dataset ;
813812 }
814813
@@ -947,10 +946,7 @@ export class LocalExecutor implements QueryExecutor {
947946 // Cache fragment sources for later use in execute()
948947 const fragments = await reader . createFragments ( source , meta . columns ) ;
949948 this . readerFragmentCache . set ( path , fragments ) ;
950- if ( this . readerFragmentCache . size > 1000 ) {
951- const firstKey = this . readerFragmentCache . keys ( ) . next ( ) . value ;
952- if ( firstKey ) this . readerFragmentCache . delete ( firstKey ) ;
953- }
949+ evictOldest ( this . readerFragmentCache , 1000 ) ;
954950 return { columns : meta . columns , fileSize } ;
955951 }
956952 throw new QueryModeError ( "INVALID_FORMAT" , `Invalid file format: unrecognized magic in ${ path } . Supported formats: .lance, .parquet, .csv, .tsv, .json, .ndjson, .jsonl, .arrow, .ipc, .feather` ) ;
0 commit comments