vortex_scan/planning/morsel.rs
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4//! The morsel side of the protocol: array-producing work and its outputs.
5
6use std::fmt;
7
8use vortex_array::ArrayRef;
9use vortex_error::VortexResult;
10use vortex_io::request::IoBatch;
11use vortex_io::request::IoConsumer;
12
13pub use crate::planning::planner::State;
14
15/// What one morsel `compute()` produced.
16///
17/// A `Batch` is never empty; a morsel that finds no rows returns `Done`. Returning `NeedsIO`
18/// registers the batch immediately, and each request in it exactly once; the next `state()`
19/// determines whether the morsel waits. Optional requests need no delivery. After `Done` the
20/// morsel is dropped without further calls.
21pub enum MorselOutput {
22 /// The morsel has finished.
23 Done,
24 /// A CPU-only checkpoint; the driver requeues the morsel.
25 Continue,
26 /// Requests the morsel publishes: fetches it needs, and optional hints.
27 NeedsIO(IoBatch),
28 /// One non-empty array of selected rows, in input-row order.
29 Batch(ArrayRef),
30}
31
32/// A morsel produces arrays for an authorised piece of work.
33///
34/// `state()` is called before every `compute()`, and `compute()` only when `state()` is
35/// `NeedsCompute`. Batches preserve selected input-row order within and across calls. A morsel
36/// moves between threads with the run that owns it.
37pub trait Morsel: IoConsumer + Send {
38 /// Reports what the morsel needs next without doing work.
39 fn state(&self) -> State;
40
41 /// Advances CPU work. Only called when [`state`](Self::state) is `NeedsCompute`.
42 fn compute(&mut self) -> VortexResult<MorselOutput>;
43}
44
45impl fmt::Debug for MorselOutput {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 match self {
48 Self::Done => f.write_str("Done"),
49 Self::Continue => f.write_str("Continue"),
50 Self::NeedsIO(batch) => f.debug_tuple("NeedsIO").field(batch).finish(),
51 Self::Batch(array) => f.debug_tuple("Batch").field(&array.len()).finish(),
52 }
53 }
54}