Assemble the "compute" side of a dataflow, i.e. all but the sources. This method imports sources from provided assets, and then builds the remaining dataflow using "compute-local" assets like shared arrangements, and producing both arrangements and sinks.
(
timely_worker: &mut TimelyWorker,
compute_state: &mut ComputeState,
dataflow: DataflowDescription<RenderPlan, CollectionMetadata>,
start_signal: StartSignal,
until: Antichain<mz_
| 196 | /// dataflow using "compute-local" assets like shared arrangements, and producing |
| 197 | /// both arrangements and sinks. |
| 198 | pub fn build_compute_dataflow( |
| 199 | timely_worker: &mut TimelyWorker, |
| 200 | compute_state: &mut ComputeState, |
| 201 | dataflow: DataflowDescription<RenderPlan, CollectionMetadata>, |
| 202 | start_signal: StartSignal, |
| 203 | until: Antichain<mz_repr::Timestamp>, |
| 204 | dataflow_expiration: Antichain<mz_repr::Timestamp>, |
| 205 | ) { |
| 206 | // Mutually recursive view definitions require special handling. |
| 207 | let recursive = dataflow |
| 208 | .objects_to_build |
| 209 | .iter() |
| 210 | .any(|object| object.plan.is_recursive()); |
| 211 | |
| 212 | // Determine indexes to export, and their dependencies. |
| 213 | let indexes = dataflow |
| 214 | .index_exports |
| 215 | .iter() |
| 216 | .map(|(idx_id, (idx, _typ))| (*idx_id, dataflow.depends_on(idx.on_id), idx.clone())) |
| 217 | .collect::<Vec<_>>(); |
| 218 | |
| 219 | // Determine sinks to export, and their dependencies. |
| 220 | let sinks = dataflow |
| 221 | .sink_exports |
| 222 | .iter() |
| 223 | .map(|(sink_id, sink)| (*sink_id, dataflow.depends_on(sink.from), sink.clone())) |
| 224 | .collect::<Vec<_>>(); |
| 225 | |
| 226 | let worker_logging = timely_worker.logger_for("timely").map(Into::into); |
| 227 | let apply_demands = COMPUTE_APPLY_COLUMN_DEMANDS.get(&compute_state.worker_config); |
| 228 | let subscribe_snapshot_optimization = |
| 229 | SUBSCRIBE_SNAPSHOT_OPTIMIZATION.get(&compute_state.worker_config); |
| 230 | |
| 231 | let name = format!("Dataflow: {}", &dataflow.debug_name); |
| 232 | let input_name = format!("InputRegion: {}", &dataflow.debug_name); |
| 233 | let build_name = format!("BuildRegion: {}", &dataflow.debug_name); |
| 234 | |
| 235 | timely_worker.dataflow_core(&name, worker_logging, Box::new(()), |_, scope| { |
| 236 | let scope = scope.with_label(); |
| 237 | |
| 238 | // The scope.clone() occurs to allow import in the region. |
| 239 | // We build a region here to establish a pattern of a scope inside the dataflow, |
| 240 | // so that other similar uses (e.g. with iterative scopes) do not require weird |
| 241 | // alternate type signatures. |
| 242 | let mut imported_sources = Vec::new(); |
| 243 | let mut tokens: BTreeMap<_, Rc<dyn Any>> = BTreeMap::new(); |
| 244 | let output_probe = MzProbeHandle::default(); |
| 245 | |
| 246 | scope.clone().region_named(&input_name, |region| { |
| 247 | // Import declared sources into the rendering context. |
| 248 | for (source_id, import) in dataflow.source_imports.iter() { |
| 249 | region.region_named(&format!("Source({:?})", source_id), |inner| { |
| 250 | let mut read_schema = None; |
| 251 | let mut mfp = import.desc.arguments.operators.clone().map(|mut ops| { |
| 252 | // If enabled, we read from Persist with a `RelationDesc` that |
| 253 | // omits uneeded columns. |
| 254 | if apply_demands { |
| 255 | let demands = ops.demand(); |
no test coverage detected