Class AsyncExternalSourceBuffer
ExchangeBuffer.
This buffer provides:
- Thread-safe page queue for cross-thread communication
- Byte-based backpressure control proportional to actual memory usage
- Notification via SubscribableListener when data becomes available
- Lifecycle management (finished state tracking)-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final longDefault byte limit for the buffer, preserving the original "10 normal-sized pages" intent. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidaddBytesRead(long delta) Addsdeltacumulative pre-decompression bytes read from the storage layer.voidaddCompletionListener(ActionListener<Void> listener) Adds a listener that will be notified when this buffer is finished.voidAdd a page to the buffer.longReturns the current number of bytes buffered, as measured byPage.ramBytesUsedByBlocks().longReturns cumulative pre-decompression bytes read from the storage layer.The mutable per-file capture sink shared with the iterator wrapping.intReturns the 1-based index of the split currently being processed by the producer.failure()booleanfinish(boolean drainingPages) Mark the buffer as finished.Returns the latest format-reader counter snapshot, ornullif none recorded yet.voidIncrements the count of splits the producer has finished processing.booleanbooleanWhether the background read dropped data under a lenient policy (seepartial).booleanvoidMark the buffer as failed.pollPage()Poll a page from the buffer.Removes and returns the next recorded warning, ornullif none remain.voidrecordFormatReaderStatus(FormatReaderStatus snapshot) Records the latest format-reader counter snapshot for the operator's status view.voidrecordInformationalWarning(String warning) Records a client-visible warning to be re-emitted on the driver thread when the operator closes, without affectingpartial.voidrecordWarning(String warning) Records a client-visible partial-results warning to be re-emitted on the driver thread when the operator closes, and flipspartial.voidsetCurrentSplit(int idx) Records the 1-based index of the split currently being processed by the producer.voidsetSplitsTotal(int total) Sets the total number of splits the producer expects to process; callable once when known.intsize()intReturns the number of splits the producer has finished processing.intReturns the total number of splits the producer expects to process.Returns anIsBlockedResultthat completes when the buffer has data for reading.Returns aSubscribableListenerthat completes when the buffer has space for writing.
-
Field Details
-
DEFAULT_MAX_BUFFER_BYTES
public static final long DEFAULT_MAX_BUFFER_BYTESDefault byte limit for the buffer, preserving the original "10 normal-sized pages" intent.
-
-
Constructor Details
-
AsyncExternalSourceBuffer
public AsyncExternalSourceBuffer(long maxBufferBytes)
-
-
Method Details
-
capturedSourceMetadataSink
The mutable per-file capture sink shared with the iterator wrapping. -
recordWarning
Records a client-visible partial-results warning to be re-emitted on the driver thread when the operator closes, and flipspartial. Thread-safe: called from the background reader / parse-worker thread.This sink is wired exclusively to the lenient
max_record_sizetruncation path (seeStreamingParallelParsingCoordinator#emitTruncationWarning): a recorded warning here always means the read returned fewer records than the source held. Per-recordSkipWarningswarnings (row skipped or field null-filled under a lenientErrorPolicy) must userecordInformationalWarning(java.lang.String)instead — not because a skipped row is never a "real" partial result, but becausepartialhas never tracked that case (this predates warning-sink relaying entirely: on the driver thread such warnings always emitted straight toHeaderWarningwithout touching this flag). Overloadingpartial's meaning to also coverSKIP_ROWdrops is a separate, pre-existing question and out of scope here. -
recordInformationalWarning
Records a client-visible warning to be re-emitted on the driver thread when the operator closes, without affectingpartial. Thread-safe: called from the background reader / parse-worker thread.Use this for warnings relayed from format-reader
SkipWarningssinks (seeFormatReadContext#informationalWarningSink()/RangeReadContext#informationalWarningSink()) — e.g. CSV/NDJSON per-record skip/null-fill handling or Parquet on-disk/planner type mismatches. This preserves these warnings' pre-existing behavior of never flippingpartial(previously they only ever reachedHeaderWarningdirectly, which has no notion ofpartialeither); this method only fixes their delivery when the read runs off the driver thread, without changing what they signal. SeerecordWarning(java.lang.String)for the one warning that has always mapped topartial.Each
SkipWarningsinstance caps its own per-event details atSkipWarnings.MAX_ADDED_WARNINGS(20), but that cap is per reader instance, not per query: a parallel or macro-split read constructs oneSkipWarningsper chunk/segment, so a single read can add well more than 20 entries topendingWarningshere — this queue itself is unbounded. -
pollWarning
Removes and returns the next recorded warning, ornullif none remain. -
isPartial
public boolean isPartial()Whether the background read dropped data under a lenient policy (seepartial). Read on the driver thread when assembling the operatorStatus. -
addPage
Add a page to the buffer. Called by the background reader thread. -
pollPage
Poll a page from the buffer. Called by the operator (driver thread).- Returns:
- the next page, or
nullif no pages available
-
waitForSpace
Returns aSubscribableListenerthat completes when the buffer has space for writing. This is the method producers use for backpressure coordination: it integrates directly with ES async patterns and the producer drain loops.- Returns:
- a listener that completes when space is available, or an already-completed listener if space exists
-
waitForReading
Returns anIsBlockedResultthat completes when the buffer has data for reading. Used by operator to signal driver when waiting for data. -
finish
public boolean finish(boolean drainingPages) Mark the buffer as finished. Called when reading is done or an error occurs.drainingPagesis honored regardless of whether this call wins thenoMoreInputstransition:AsyncExternalSourceOperator.close()always callsfinish(true), and by the time a driver closes its operatornoMoreInputshas very often already been set by the producer's ownonFailure(java.lang.Throwable)or an earlierfinish(false)— e.g. the producer reached natural EOF, or the read failed, before the driver got a chance to drain every page viagetOutput()/pollPage(). GatingdiscardPages()behind the transition used to skip it entirely in that (common) case, leaking whatever the producer had already buffered when the driver's close is not preceded by a full drain (e.g. cross-driver task cancellation cutting this operator before its own poll loop ever ran).- Returns:
trueif this call performed the running→finishing transition;falseif the buffer had already been finished (e.g. producer reached natural EOF, or a concurrentfinish/onFailurebeat us to it). The stop-hook path inAsyncExternalSourceOperatorFactoryuses this to distinguish "STOP genuinely cut a running producer" (partial result) from "STOP raced with natural completion" (honestly complete result).
-
onFailure
Mark the buffer as failed. Called when the background reader encounters an error.Queued pages are retained so the driver can drain them before
AsyncExternalSourceOperatorsurfaces the failure viaOperator.getOutput(). -
isFinished
public boolean isFinished() -
noMoreInputs
public boolean noMoreInputs() -
size
public int size() -
addCompletionListener
Adds a listener that will be notified when this buffer is finished. -
failure
-
bytesInBuffer
public long bytesInBuffer()Returns the current number of bytes buffered, as measured byPage.ramBytesUsedByBlocks(). -
recordFormatReaderStatus
Records the latest format-reader counter snapshot for the operator's status view. -
addBytesRead
public void addBytesRead(long delta) Addsdeltacumulative pre-decompression bytes read from the storage layer. -
setSplitsTotal
public void setSplitsTotal(int total) Sets the total number of splits the producer expects to process; callable once when known. -
incSplitsProcessed
public void incSplitsProcessed()Increments the count of splits the producer has finished processing. -
setCurrentSplit
public void setCurrentSplit(int idx) Records the 1-based index of the split currently being processed by the producer. -
formatReaderStatus
Returns the latest format-reader counter snapshot, ornullif none recorded yet. -
bytesRead
public long bytesRead()Returns cumulative pre-decompression bytes read from the storage layer. -
splitsTotal
public int splitsTotal()Returns the total number of splits the producer expects to process. -
splitsProcessed
public int splitsProcessed()Returns the number of splits the producer has finished processing. -
currentSplit
public int currentSplit()Returns the 1-based index of the split currently being processed by the producer.Semantics differ slightly between producer paths and the value should not be compared across them: the slice-queue path counts top-level splits pulled from the queue (a coalesced split with N leaves still increments the index by 1, not N), while the file-list / multi-file path uses the absolute file index. Use this for "where am I in the work" UX in a single-query profile, not for cross-query comparison or rate math.
-