You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Compute workers iterate arrangements synchronously while serving
index-backed peeks, so a query that scans far more rows than it returns
can hold a worker for a long time and delay everything else on the
cluster. Persist fast-path peeks have the same shape: filtering happens
after the rows have been read.
Add an off-by-default failsafe that bounds how many rows a worker may
examine for one peek. Two dyncfgs, a feature gate and a threshold that
defaults to 1000 rows, both read through handles so that an
`UpdateConfiguration` reaches peeks that are already in flight. The
budget covers the index result trace, the index error trace and the
Persist fast path, and counts rows before literal and MFP filtering,
because a row that is read and then discarded costs the same scan time
as one that is returned. Exactly the configured number of rows may be
examined. A peek fails only when it asks for the row after that.
The limit deliberately stops at the peek stash. A stashed peek restarts
its scan and produces in bounded bursts, so bounding it needs the count
to survive the hand-off, and the restart makes that count charge the
same rows twice. Leaving it out keeps this change small. The peeks that
motivate the failsafe, large filtered scans, fail before they ever reach
the stash threshold.
Reporting the limit needs an error type that survives the trip from the
worker. `PeekResponse::Error` carried a bare `String`, so every peek
failure reached the adapter as `AdapterError::Unstructured` and was
reported as XX000. Give it a `PeekError` of `Dataflow`, `Unstructured`
or `RowIterationLimitExceeded`, and let `PeekResponseUnary::Error` carry
an `AdapterError`, so the conversion happens once instead of once per
frontend. The limit then reports SQLSTATE 54000 with a hint naming the
threshold parameter, and worker responses merge by error precedence:
cancellation, then ordinary errors, then the limit.
Carrying the dataflow error structurally also fixes the SQLSTATE of
evaluation errors raised while reading a collection: `SELECT a / b FROM
t` now reports 22012 like its constant-folded counterpart. Such an error
keeps the message `DataflowError` renders, so one that used to come back
bare from an index or Persist fast-path MFP now carries the `Evaluation
error:` prefix the error-trace path already used.
The wire encoding is bincode, which cannot skip a variant it does not
know, so `PeekResponse` serializes through a mirror type that keeps
`Error(String)` where it was for the unstructured case and appends the
structured one. Existing frames, `Canceled` in particular, encode
exactly as before.
The test and CI configuration enables the feature with a high threshold,
so the guarded path is exercised broadly without constraining ordinary
queries.
0 commit comments