Class AsyncExternalSourceOperatorFactory
java.lang.Object
org.elasticsearch.xpack.esql.datasources.AsyncExternalSourceOperatorFactory
- All Implemented Interfaces:
Describable,Operator.OperatorFactory,SourceOperator.SourceOperatorFactory,DeferredExtractionCapable
public class AsyncExternalSourceOperatorFactory
extends Object
implements SourceOperator.SourceOperatorFactory, DeferredExtractionCapable
Dual-mode async factory for creating source operators that read from external storage.
This factory automatically selects the optimal execution mode based on the FormatReader's capabilities:
- Sync Wrapper Mode: For simple formats (CSV, JSON) that don't have native async
support. The sync
FormatReader.read(org.elasticsearch.xpack.esql.datasources.spi.StorageObject, org.elasticsearch.xpack.esql.datasources.spi.FormatReadContext)method is wrapped in a background thread from the ES ThreadPool. - Native Async Mode: For async-capable formats (Parquet with parallel row groups)
that implement
FormatReader.readAsync(org.elasticsearch.xpack.esql.datasources.spi.StorageObject, org.elasticsearch.xpack.esql.datasources.spi.FormatReadContext, java.util.concurrent.Executor, org.elasticsearch.action.ActionListener<org.elasticsearch.compute.operator.CloseableIterator<org.elasticsearch.compute.data.Page>>). This avoids wrapper thread overhead by letting the reader control its own threading.
Key design principles:
- Simple things stay simple - CSV/JSON readers just implement sync read()
- Async when beneficial - Parquet can override readAsync() for parallel I/O
- ES ThreadPool integration - All executors come from ES, not standalone threads
- Backpressure via buffer - Uses
AsyncExternalSourceBufferwith waitForSpace()
Two executors, deliberately on different pools so the parser workers and the consumer that drains their pages never contend for the same threads:
executor— the read/parse pool. Runs the blocking file opens (length(),computeSegments) and the segment parser workers. Sourced fromSourceOperatorContext.fileReadExecutor— the dedicatedesql_external_iopool — falling back tocontext.executor()when unset.producerExecutor— the consumer pool. Runs the (non-blocking) producer/drain loop that consumes the parser workers' pages into the buffer. Sourced fromcontext.executor()—esql_worker, the same compute pool whose driversAsyncExternalSourceBuffer.pollPage()— falling back toexecutorwhen unset (single-pool test callers).
producerExecutor when space is freed.- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classFluent builder forAsyncExternalSourceOperatorFactory. -
Method Summary
Modifier and TypeMethodDescriptionintbuilder(StorageProvider storageProvider, FormatReader formatReader, StoragePath path, List<Attribute> attributes, int batchSize, int maxBufferSize, Executor executor) booleanWhether deferred field extraction is enabled on this factory.describe()executor()fileList()get(DriverContext driverContext) intintpath()introwLimit()voidsetMinCompetitiveSupplier(SharedMinCompetitive.Supplier minCompetitiveSupplier, String columnName, boolean ascending, boolean nullsFirst) Installs the sharedBYTES_REFcompetitive threshold for a single keyword/text sort key, fed by the genericTopNOperator'sSharedMinCompetitiveside-channel.voidsetNumericThresholdSupplier(SharedNumericThreshold.Supplier thresholdSupplier, String columnName, ElementType elementType, boolean ascending, boolean nullsFirst) Installs the shared numeric TopN threshold.sourceExtractorsFor(DriverContext driverContext) Resolves (or lazily creates) theSourceExtractorsregistry shared between this factory's source operator and a pairedExternalFieldExtractOperatorfor the same driver.
-
Method Details
-
builder
public static AsyncExternalSourceOperatorFactory.Builder builder(StorageProvider storageProvider, FormatReader formatReader, StoragePath path, List<Attribute> attributes, int batchSize, int maxBufferSize, Executor executor) -
get
- Specified by:
getin interfaceOperator.OperatorFactory- Specified by:
getin interfaceSourceOperator.SourceOperatorFactory
-
sourceExtractorsFor
Resolves (or lazily creates) theSourceExtractorsregistry shared between this factory's source operator and a pairedExternalFieldExtractOperatorfor the same driver. The registry is populated as files are opened and read via the registeredColumnExtractor.extract(java.lang.String[], org.elasticsearch.xpack.esql.core.type.DataType[], long[], org.elasticsearch.compute.data.BlockFactory)contract.Only meaningful when
AsyncExternalSourceOperatorFactory.Builder.deferredExtractionwas enabled. Calls during the non-deferred mode return a fresh empty registry; callers in that mode should not depend on its contents.- Specified by:
sourceExtractorsForin interfaceDeferredExtractionCapable
-
deferredExtractionEnabled
public boolean deferredExtractionEnabled()Whether deferred field extraction is enabled on this factory. SeeAsyncExternalSourceOperatorFactory.Builder.deferredExtraction(boolean)for semantics. -
describe
- Specified by:
describein interfaceDescribable
-
storageProvider
-
formatReader
-
path
-
attributes
-
batchSize
public int batchSize() -
maxBufferSize
public int maxBufferSize() -
rowLimit
public int rowLimit() -
executor
-
fileList
-
partitionColumnNames
-
partitionValues
-
sliceQueue
-
errorPolicy
-
parsingParallelism
public int parsingParallelism()
-