From 7eebd8a90b1a2d6bf84f9daf6da99864f673e575 Mon Sep 17 00:00:00 2001 From: zz_y Date: Wed, 2 Sep 2026 18:44:49 -0600 Subject: [PATCH] refactor(control-plane): remove sketch algebra layer --- README.md | 4 +- control_plane/proto/backend_plan.proto | 2 +- control_plane/src/asap_tier_analysis.rs | 2 +- control_plane/src/asap_tier_implement.rs | 2 +- control_plane/src/emit/mod.rs | 18 ++++---- control_plane/src/emit/stage_config.rs | 8 ++-- control_plane/src/lib.rs | 8 +--- control_plane/src/main.rs | 20 ++++----- .../src/physical/colored_dag/allocator.rs | 26 ++++++----- control_plane/src/physical/colored_dag/dag.rs | 4 +- .../src/physical/colored_dag/emitter.rs | 14 +++--- control_plane/src/physical/colored_dag/mod.rs | 2 +- .../src/physical/colored_dag/tests.rs | 35 ++++++++------- control_plane/src/physical/compiler.rs | 2 +- .../deployment_cost/sketch_capability.rs | 4 +- .../src/physical/deployment_cost/wire.rs | 6 +-- control_plane/src/physical/mod.rs | 3 +- .../post_asap}/cost_model.rs | 2 +- .../post_asap/deployment_expr.rs} | 44 +++++++++---------- .../post_asap}/lower.rs | 21 +++++---- .../post_asap}/matcher.rs | 0 control_plane/src/physical/post_asap/mod.rs | 22 ++++++++++ .../post_asap}/tests.rs | 44 ++++++++++--------- .../src/physical/runtime_capability.rs | 6 +-- control_plane/src/physical/stage_split.rs | 18 ++++---- .../src/physical/workload_planner.rs | 17 +++---- control_plane/src/replan.rs | 10 ++--- control_plane/src/sketch_algebra/mod.rs | 43 ------------------ control_plane/src/sketch_selection.rs | 2 +- control_plane/src/types.rs | 4 +- .../asap_query_engine/post_asap_planner.rs | 12 ++--- ...e2e_controller_plans_and_backend_serves.rs | 4 +- 32 files changed, 197 insertions(+), 212 deletions(-) rename control_plane/src/{sketch_algebra => physical/post_asap}/cost_model.rs (99%) rename control_plane/src/{sketch_algebra/physical_expr.rs => physical/post_asap/deployment_expr.rs} (87%) rename control_plane/src/{sketch_algebra => physical/post_asap}/lower.rs (93%) rename control_plane/src/{sketch_algebra => physical/post_asap}/matcher.rs (100%) create mode 100644 control_plane/src/physical/post_asap/mod.rs rename control_plane/src/{sketch_algebra => physical/post_asap}/tests.rs (96%) delete mode 100644 control_plane/src/sketch_algebra/mod.rs diff --git a/README.md b/README.md index d2b3bf43..fc5be783 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ ASAPQuery-backend/ # Cargo workspace │ └── src/ │ ├── query_parser/ # PromQL/SQL parsing → intent algebra │ ├── intent_algebra/ # shared intent representation -│ ├── sketch_algebra/ # sketch planning (+ rules/) +│ ├── physical/post_asap/ # physical adapters for Planner post-ASAP IR │ ├── optimizer/ # plan optimization (cost/ + rules/) │ ├── physical/ # physical plan (colored_dag/) │ ├── emit/ # per-runtime config emission @@ -233,7 +233,7 @@ that produced the current architecture: - **Sketch placement planner** — moved into [`ASAPCollector/controller/`](https://github.com/ProjectASAP/ASAPCollector/tree/main/controller) - **PromQL pattern matchers for the planner** — migrated into the - controller's L3 `intent_algebra` + L4 `sketch_algebra` + ASAPPlanner's post-ASAP IR plus backend physical placement - **JSONL cold-fallback path** — deleted; the configured exact backend is the explicit fallback described by [query-engine implementation design](docs/developer_docs/query-engine/design.md). diff --git a/control_plane/proto/backend_plan.proto b/control_plane/proto/backend_plan.proto index 9b6db033..b1aaebc3 100644 --- a/control_plane/proto/backend_plan.proto +++ b/control_plane/proto/backend_plan.proto @@ -43,7 +43,7 @@ message SummaryParams { } } -// ── Capability (control_plane::sketch_algebra::capability) ────────────────── +// ── Capability (control_plane::physical::post_asap::capability) ────────────────── enum SketchKindHandle { SKETCH_KIND_HANDLE_UNSPECIFIED = 0; diff --git a/control_plane/src/asap_tier_analysis.rs b/control_plane/src/asap_tier_analysis.rs index 45319f3f..0e78fa4a 100644 --- a/control_plane/src/asap_tier_analysis.rs +++ b/control_plane/src/asap_tier_analysis.rs @@ -42,7 +42,7 @@ //! exist in real PromQL/MetricsQL; the lowerer handles the real //! names like `quantile_over_time` and `count_over_time`). //! - The local `Capability` / `SketchKindHandle` enums — they're now -//! re-exported from `sketch_algebra` (the single source of truth). +//! re-exported from `physical::post_asap` (the single source of truth). use std::collections::BTreeSet; use std::time::Duration; diff --git a/control_plane/src/asap_tier_implement.rs b/control_plane/src/asap_tier_implement.rs index e7609776..627fc91d 100644 --- a/control_plane/src/asap_tier_implement.rs +++ b/control_plane/src/asap_tier_implement.rs @@ -10,7 +10,7 @@ //! four already-distinct senses of "bind" in this stack (L2 name //! resolution `ColumnRef → ColumnId`; the L3→L4 per-node physical //! choice; a deployment's own L4→L5 *placement* decision, e.g. -//! `control_plane::sketch_algebra::rules::bind_*`; and this module's own +//! `control_plane::physical::post_asap::rules::bind_*`; and this module's own //! prior usage) and deliberately names its L3→L4 step **"implementation"** //! instead (Cascades/Volcano terminology: an *implementation rule* is //! logical → physical, distinct from a *transformation rule*, logical → diff --git a/control_plane/src/emit/mod.rs b/control_plane/src/emit/mod.rs index 10f991bb..20c5336a 100644 --- a/control_plane/src/emit/mod.rs +++ b/control_plane/src/emit/mod.rs @@ -46,8 +46,8 @@ pub use telegraf::emit_telegraf_toml; pub use crate::workload::WorkloadRegistry; use crate::physical::colored_dag::emitter::EdgeStageConfig; -use crate::sketch_algebra::physical_expr::L4Plan; -use crate::sketch_algebra::PhysicalExpr; +use crate::physical::post_asap::deployment_expr::PostAsapPlan; +use crate::physical::post_asap::PhysicalExpr; use crate::store::WorkloadStore; use anyhow::Result; use planner_types::post_asap::{SketchAlgorithm, SummaryExpr, SummaryNode}; @@ -295,13 +295,13 @@ pub fn extract_root_sketch_kind(expr: &PhysicalExpr) -> Option } } -fn extract_from_plan(plan: &L4Plan) -> Option { +fn extract_from_plan(plan: &PostAsapPlan) -> Option { match plan { - L4Plan::Summary(node) => extract_from_node(node), - L4Plan::LetBinding { expr, child, .. } => { + PostAsapPlan::Summary(node) => extract_from_node(node), + PostAsapPlan::LetBinding { expr, child, .. } => { extract_from_plan(expr).or_else(|| extract_from_plan(child)) } - L4Plan::Ref { .. } => None, + PostAsapPlan::Ref { .. } => None, } } @@ -323,7 +323,7 @@ fn extract_from_node(node: &Rc) -> Option { SummaryExpr::SummaryEstimate { summary_input, .. } => extract_from_node(summary_input), SummaryExpr::SummaryMerge { children } => children.iter().find_map(extract_from_node), // Not surfaced by any `Bind*` path yet (gated on rules that - // haven't landed — see `physical_expr.rs`'s module docs). + // haven't landed — see `deployment_expr.rs`'s module docs). SummaryExpr::SummaryJoin { .. } | SummaryExpr::SummarySubtract { .. } | SummaryExpr::SummaryDelete { .. } @@ -389,7 +389,7 @@ pub fn collect_metric_to_family( .get(label) .map(|v| (label, v.as_str())) }); - let Some(physical_expr) = + let Some(deployment_expr) = crate::physical::workload_planner::bind_workload_typed_with_item_filter( &workload, item_filter, @@ -397,7 +397,7 @@ pub fn collect_metric_to_family( else { continue; }; - if let Some(kind) = extract_root_sketch_kind(&physical_expr) { + if let Some(kind) = extract_root_sketch_kind(&deployment_expr) { out.entry(entry.metric_name.clone()) .or_default() .insert(kind); diff --git a/control_plane/src/emit/stage_config.rs b/control_plane/src/emit/stage_config.rs index adcf9121..2392e562 100644 --- a/control_plane/src/emit/stage_config.rs +++ b/control_plane/src/emit/stage_config.rs @@ -899,7 +899,7 @@ fn build_routing_entry(metric_name: &str, cfg: &BackendStageConfig) -> JsonValue warm_shapes.push("count"); } // Heap-bearing kinds count too — `SummaryKind` (unlike the retired - // `sketch_algebra::SummaryKind`) promotes `with_heap` to a distinct + // `physical::post_asap::SummaryKind`) promotes `with_heap` to a distinct // identity variant, but a topk-bound Count-Sketch/CMS aggregation // still needs to register here exactly as it did before the split. let has_count_sketch = kinds.iter().any(|k| { @@ -3037,7 +3037,7 @@ fn build_backend_readout_json(r: &BackendReadout) -> JsonValue { /// The wire-string key for a `SketchQuery::PointCount` readout. /// /// `SampleValue` and `Wildcard` both wire to the legacy `"*"` sentinel -/// (`sketch_algebra::rules::bind_cms_count`, retired by Step B, used the +/// (`physical::post_asap::rules::bind_cms_count`, retired by Step B, used the /// literal string `"*"` to mean "all rows / no specific key"; the L5 /// emitter's per-group resolution already special-cases that string) — /// there's no real queryable column for a plain `Count`/`Frequency` @@ -3056,7 +3056,7 @@ fn column_ref_to_wire_key(col: &ColumnRef) -> String { /// The 5-sketch routing-connector edge YAML path (`emit_edge_yaml`'s /// `USE_5SKETCH_ROUTING` branch and its `metric_to_family` sibling) /// keys its fixed `FAMILY_ORDER` list and lookup maps on the 5 bare -/// families only — matching the retired `sketch_algebra::SketchAlgorithm`, +/// families only — matching the retired `physical::post_asap::SketchAlgorithm`, /// which had no heap-bearing variant at all (`with_heap` was a /// `SketchParams` field, invisible to anything keying on kind alone). /// A committed heap-bearing kind (`CmsWithHeap`/`CountSketchWithHeap`, @@ -3079,7 +3079,7 @@ fn base_family(kind: &SketchAlgorithm) -> SketchAlgorithm { /// /// Heap-bearing is now identity, not a params flag (`SketchAlgorithm::CmsWithHeap` /// / `CountSketchWithHeap`, set by `BindCountSketchOnTopK` — see -/// `sketch_algebra::rules::bind_cms_topk`), so this maps on `kind` alone; +/// `physical::post_asap::rules::bind_cms_topk`), so this maps on `kind` alone; /// `params` is unused but kept for call-site stability. This is what /// lets the backend's `policy_capability` lookup return /// `FrequencyTopk(*WithHeap)` for heap-bearing aggregations — required diff --git a/control_plane/src/lib.rs b/control_plane/src/lib.rs index 7511b33f..a71a6db5 100644 --- a/control_plane/src/lib.rs +++ b/control_plane/src/lib.rs @@ -38,8 +38,6 @@ //! | `controller/src/config/{stage_config*,agent,backend,asapquery_backend,precompute}.rs` | `controller/src/emit/{...}.rs` | //! //! Public modules to consume from `asap-query-engine`: -//! - `sketch_algebra` — `Capability` enum + `capability_for(agg_intent: &AggIntent)` -//! lookup table (Phase 4 / 5 use this to route raw-name PromQL). //! - `intent_algebra` — `AggIntent` + `QueryExpr` DAG (canonical L3 IR; //! `relational` carries the L2 relational IR the parsers emit and //! `lower` lowers it to the canonical L3 types). @@ -73,7 +71,6 @@ pub mod query_parser; pub mod query_planning; pub mod replan; pub mod runtime_samples; -pub mod sketch_algebra; pub mod sketch_selection; pub mod store; pub mod threshold_alloc; @@ -95,9 +92,8 @@ pub mod workload; /// the module docs for the full PromQL shape coverage matrix. pub mod asap_tier_analysis; -/// PromQL → compositional L4 plan via `asap_aware_mapping::bind::implement_tree`. -/// Step A of the plan-shaped-serving scoping (see module doc) -- not yet -/// wired into the live serving path. +/// PromQL → ASAPPlanner's canonical post-ASAP plan via +/// `asap_aware_mapping::bind::implement_tree`. pub mod asap_tier_implement; /// Crate-wide test-only utilities for serialising access to process-global diff --git a/control_plane/src/main.rs b/control_plane/src/main.rs index 025109f6..a4fdeda7 100644 --- a/control_plane/src/main.rs +++ b/control_plane/src/main.rs @@ -5,11 +5,11 @@ use control_plane::metrics_exposer; use control_plane::monitor; use control_plane::opamp; use control_plane::physical; +use control_plane::physical::post_asap; use control_plane::pipeline; use control_plane::query_parser; use control_plane::replan; use control_plane::runtime_samples; -use control_plane::sketch_algebra; use control_plane::store; use control_plane::types; use control_plane::types_v2; @@ -779,7 +779,7 @@ async fn handle_plan(State(st): State, Json(spec): Json) -> // is no `query_string`. let raw_bps = plan.transmission_cost_summary.raw_bytes_per_sec; let budgets = StageResourceBudgets::from_workload_chars(&wc); - // Everything that touches `sketch_algebra::PhysicalExpr` (which + // Everything that touches `physical::post_asap::PhysicalExpr` (which // carries `Rc` since Step B of the // plan-shaped-serving migration adopted ASAPController's own // `Rc`-based DAG sharing) is scoped to this block and resolved down @@ -789,7 +789,7 @@ async fn handle_plan(State(st): State, Json(spec): Json) -> // yield point would make its `Future` `!Send`, breaking // `axum::Handler`. let (plan_summary, stage_configs) = { - let mut bound_physical: Option = None; + let mut bound_physical: Option = None; let mut plan_summary = None; if let Some(ref qs) = query_string { match parse_query_expr_canonical(qs, accuracy) { @@ -807,7 +807,7 @@ async fn handle_plan(State(st): State, Json(spec): Json) -> ) }; bound_physical = - control_plane::sketch_algebra::bind_query_expr(&qe, accuracy).ok(); + control_plane::physical::post_asap::bind_query_expr(&qe, accuracy).ok(); // Cost summary for the JSON response. let plan_node = SketchAllocator::new(budgets.clone(), raw_bps).allocate(qe); plan_summary = Some(plan_node.summarise(raw_bps)); @@ -821,9 +821,9 @@ async fn handle_plan(State(st): State, Json(spec): Json) -> crate::physical::colored_dag::StageConfig, >, > = if physical::stage_split::typed_stage_split_enabled() { - let physical_expr = bound_physical + let deployment_expr = bound_physical .or_else(|| physical::workload_planner::bind_workload_typed(&workload)); - physical_expr.and_then(|pe| physical::stage_split::split_typed_three_stage(&pe)) + deployment_expr.and_then(|pe| physical::stage_split::split_typed_three_stage(&pe)) } else { None }; @@ -883,7 +883,7 @@ async fn handle_plan(State(st): State, Json(spec): Json) -> // // The typed L5 stage-split is now fed by the real **L4 output**: when // the spec carries a `query_string`, `bound_physical` holds the - // optimised L3 tree run through `sketch_algebra::bind_query_expr`. + // optimised L3 tree run through `physical::post_asap::bind_query_expr`. // For specs that supply only explicit fields (no `query_string` to // parse), there is no L3 tree to bind, so we fall back to // `bind_workload_typed`, which lowers the flat `QueryWorkload` @@ -1616,7 +1616,7 @@ async fn emit_bootstrap_typed( // typed bind, so for `http_requests_total` the // Quantile-shaped role on `http_requests_total_latency_ms` // stays the source of the edge config. - let mut chosen: Option<(String, crate::sketch_algebra::PhysicalExpr)> = None; + let mut chosen: Option<(String, crate::physical::post_asap::PhysicalExpr)> = None; 'outer: for cand in &candidates { for (_, wl, _) in st.workload_store.get_all_for_metric(cand) { if let Some(expr) = physical::workload_planner::bind_workload_typed(&wl) { @@ -1625,13 +1625,13 @@ async fn emit_bootstrap_typed( } } } - let (metric, physical_expr) = chosen.ok_or_else(|| { + let (metric, deployment_expr) = chosen.ok_or_else(|| { anyhow!( "no registry metric binds via the typed path (all {} candidates declined)", candidates.len() ) })?; - let configs = physical::stage_split::split_typed_three_stage(&physical_expr) + let configs = physical::stage_split::split_typed_three_stage(&deployment_expr) .ok_or_else(|| anyhow!("split_typed_three_stage returned None for `{metric}`"))?; // 4. Pick the Edge stage config and emit per-runtime. The diff --git a/control_plane/src/physical/colored_dag/allocator.rs b/control_plane/src/physical/colored_dag/allocator.rs index 91d23191..ae260412 100644 --- a/control_plane/src/physical/colored_dag/allocator.rs +++ b/control_plane/src/physical/colored_dag/allocator.rs @@ -43,8 +43,8 @@ use planner_types::post_asap::{SummaryExpr, SummaryNode}; use crate::physical::colored_dag::dag::{ColoredDag, ColoredNode, NodeId}; use crate::physical::colored_dag::stage_id::{StageId, Topology}; -use crate::sketch_algebra::physical_expr::L4Plan; -use crate::sketch_algebra::PhysicalExpr; +use crate::physical::post_asap::deployment_expr::PostAsapPlan; +use crate::physical::post_asap::PhysicalExpr; use crate::types_v2::BindingName; /// Errors surfaced by [`StageAllocator::allocate`]. @@ -124,18 +124,18 @@ impl ThreeStageWalker { } } - /// Recursively visit an [`L4Plan`] — the "what to compute" layer. - /// [`L4Plan::Summary`] delegates the actual per-node granularity to + /// Recursively visit an [`PostAsapPlan`] — the "what to compute" layer. + /// [`PostAsapPlan::Summary`] delegates the actual per-node granularity to /// [`Self::visit_l4node`] (walking `planner_types::post_asap::SummaryNode`'s own DAG - /// shape); [`L4Plan::LetBinding`] / [`L4Plan::Ref`] are this crate's + /// shape); [`PostAsapPlan::LetBinding`] / [`PostAsapPlan::Ref`] are this crate's /// own named-binding sharing mechanism, unchanged from before Step B. - fn visit_plan(&mut self, plan: &L4Plan) -> Result<(NodeId, StageId), AllocateError> { + fn visit_plan(&mut self, plan: &PostAsapPlan) -> Result<(NodeId, StageId), AllocateError> { match plan { - L4Plan::Summary(node) => self.visit_l4node(node), + PostAsapPlan::Summary(node) => self.visit_l4node(node), // ── LetBinding: colour by the bound expression's stage, // and bring the binding into scope before walking the body. - L4Plan::LetBinding { name, expr, child } => { + PostAsapPlan::LetBinding { name, expr, child } => { let id = self.reserve_node(PhysicalExpr::Committed(plan.clone())); let (eid, expr_stage) = self.visit_plan(expr)?; self.dag.edges.push((id, eid)); @@ -147,7 +147,7 @@ impl ThreeStageWalker { // ── Ref: colour matches the binding's stage. Unresolved // refs bubble up as `AllocateError::UnresolvedRef`. - L4Plan::Ref { name } => { + PostAsapPlan::Ref { name } => { let id = self.reserve_node(PhysicalExpr::Committed(plan.clone())); let stage = self .scope @@ -163,7 +163,7 @@ impl ThreeStageWalker { /// itself, owned upstream. Every semantic node gets its own /// [`ColoredNode`] (matching the granularity the old, locally-defined /// `PhysicalExpr::{SketchAgg,SketchEstimate,SketchMerge}` had), - /// stored back as `PhysicalExpr::Committed(L4Plan::Summary(..))` + /// stored back as `PhysicalExpr::Committed(PostAsapPlan::Summary(..))` /// wrapping just that sub-node, so downstream consumers /// (`colored_dag::emitter`, `emit::mod`) keep pattern-matching /// against the same `PhysicalExpr` shape. @@ -214,7 +214,7 @@ impl ThreeStageWalker { // ── SummaryJoin / SummarySubtract / SummaryDelete: not // surfaced by any `Bind*` path yet (gated on rules that - // haven't landed — see `physical_expr.rs`'s module docs' + // haven't landed — see `deployment_expr.rs`'s module docs' // predecessor note). Conservative default matching // SummaryMerge's multi-input-combination shape until a real // consumer picks a placement. @@ -320,7 +320,9 @@ impl ThreeStageWalker { // stage lookup keyed by binding name. pub(crate) fn binding_stage(dag: &ColoredDag, name: &BindingName) -> Option { dag.nodes.iter().find_map(|n| match &n.expr { - PhysicalExpr::Committed(L4Plan::LetBinding { name: n2, .. }) if n2 == name => Some(n.stage), + PhysicalExpr::Committed(PostAsapPlan::LetBinding { name: n2, .. }) if n2 == name => { + Some(n.stage) + } _ => None, }) } diff --git a/control_plane/src/physical/colored_dag/dag.rs b/control_plane/src/physical/colored_dag/dag.rs index c23c5ef5..f0e3eda4 100644 --- a/control_plane/src/physical/colored_dag/dag.rs +++ b/control_plane/src/physical/colored_dag/dag.rs @@ -23,7 +23,7 @@ use serde::{Deserialize, Serialize}; use crate::physical::colored_dag::stage_id::{StageId, Topology}; -use crate::sketch_algebra::PhysicalExpr; +use crate::physical::post_asap::PhysicalExpr; /// Stable position-based identifier for a node within a `ColoredDag`. /// `NodeId(0)` is the root; depth-first walk order otherwise. @@ -146,7 +146,7 @@ mod tests { use std::rc::Rc; use super::*; - use crate::sketch_algebra::PhysicalExpr; + use crate::physical::post_asap::PhysicalExpr; use planner_types::pre_asap::{Column, DataType}; use planner_types::pre_asap::{QueryExpr, Schema, Source}; diff --git a/control_plane/src/physical/colored_dag/emitter.rs b/control_plane/src/physical/colored_dag/emitter.rs index bcc1f978..b1eba063 100644 --- a/control_plane/src/physical/colored_dag/emitter.rs +++ b/control_plane/src/physical/colored_dag/emitter.rs @@ -33,7 +33,7 @@ use serde::{Deserialize, Serialize}; use crate::physical::colored_dag::dag::ColoredDag; use crate::physical::colored_dag::stage_id::{StageId, Topology}; -use crate::sketch_algebra::physical_expr::{L4Plan, PhysicalExpr}; +use crate::physical::post_asap::deployment_expr::{PhysicalExpr, PostAsapPlan}; use crate::types_v2::BindingName; use planner_types::post_asap::{SketchAlgorithm, SketchParams, SketchQuery, SummaryExpr}; // `BackendAggregation.sketch_kind`/`.sketch_params` (below) span BOTH @@ -53,7 +53,7 @@ use asap_types::{SummaryKind as BackendSketchKind, SummaryParams as BackendSketc /// `PhysicalExpr`, for the tuple-style `(&node.expr, node.stage)` matching /// this file uses throughout. Mirrors the shape the old, locally-defined /// flat `PhysicalExpr` had before Step B folded most of its variants into -/// `planner_types::post_asap::SummaryExpr` — see `sketch_algebra::physical_expr`'s +/// `planner_types::post_asap::SummaryExpr` — see `physical::post_asap::deployment_expr`'s /// module docs. enum NodeKind<'a> { Logical(&'a planner_types::pre_asap::QueryExpr), @@ -95,7 +95,7 @@ enum NodeKind<'a> { fn classify(expr: &PhysicalExpr) -> NodeKind<'_> { match expr { - PhysicalExpr::Committed(L4Plan::Summary(node)) => match &node.expr { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => match &node.expr { SummaryExpr::KeepPreAsap(qe) => NodeKind::Logical(qe), // `SummaryAgg`'s `kind`/`params` fields collapsed into one // `family: SummaryFamilyType` field (ASAPPlanner#218 -- @@ -126,8 +126,10 @@ fn classify(expr: &PhysicalExpr) -> NodeKind<'_> { | SummaryExpr::SummarySubtract { .. } | SummaryExpr::SummaryDelete { .. } => NodeKind::Other, }, - PhysicalExpr::Committed(L4Plan::LetBinding { name, .. }) => NodeKind::LetBinding { name }, - PhysicalExpr::Committed(L4Plan::Ref { name }) => NodeKind::Ref { name }, + PhysicalExpr::Committed(PostAsapPlan::LetBinding { name, .. }) => { + NodeKind::LetBinding { name } + } + PhysicalExpr::Committed(PostAsapPlan::Ref { name }) => NodeKind::Ref { name }, PhysicalExpr::RawAtEdgeSketchAtBackend { family, params, .. } => { NodeKind::RawAtEdgeSketchAtBackend { family, params } } @@ -1068,7 +1070,7 @@ impl Emitter for ThreeStageEmitter { /// crates in `opentelemetry-collector-contrib`) already use. /// /// Heap-bearing kinds (`CmsWithHeap`/`CountSketchWithHeap`) reuse their -/// bare counterpart's processor name — the retired `sketch_algebra::SketchAlgorithm` +/// bare counterpart's processor name — the retired `physical::post_asap::SketchAlgorithm` /// this replaces had no heap-bearing variant at all (`with_heap` was a /// `SketchParams` field this function never received), so heap-bearing /// and bare CMS/CountSketch already mapped to the identical processor diff --git a/control_plane/src/physical/colored_dag/mod.rs b/control_plane/src/physical/colored_dag/mod.rs index fb8a2af7..ed51d564 100644 --- a/control_plane/src/physical/colored_dag/mod.rs +++ b/control_plane/src/physical/colored_dag/mod.rs @@ -5,7 +5,7 @@ //! typed L5 colouring + emitter for the DC three-stage topology //! (edge → gateway → backend). //! -//! Pipeline position. L4 [`crate::sketch_algebra::PhysicalExpr`] is the +//! Pipeline position. L4 [`crate::physical::post_asap::PhysicalExpr`] is the //! input — sketch-bound, language-orthogonal, deployment-independent. //! L5 paints each `PhysicalExpr` node with a [`StageId`] and emits one //! [`emitter::StageConfig`] per occupied stage. The configs become the diff --git a/control_plane/src/physical/colored_dag/tests.rs b/control_plane/src/physical/colored_dag/tests.rs index f893cf21..a203fe8a 100644 --- a/control_plane/src/physical/colored_dag/tests.rs +++ b/control_plane/src/physical/colored_dag/tests.rs @@ -18,7 +18,7 @@ use planner_types::post_asap::{ use crate::physical::colored_dag::allocator::StageAllocator; use crate::physical::colored_dag::emitter::{EmitError, Emitter, StageConfig, ThreeStageEmitter}; use crate::physical::colored_dag::stage_id::{StageId, Topology}; -use crate::sketch_algebra::physical_expr::{L4Plan, PhysicalExpr}; +use crate::physical::post_asap::deployment_expr::{PhysicalExpr, PostAsapPlan}; use crate::types_v2::{AccuracyTarget, BindingName}; use planner_types::pre_asap::{Column, DataType}; use planner_types::pre_asap::{ColumnRef, QueryExpr, Reduction, Schema, Source}; @@ -135,7 +135,7 @@ fn estimate_l4(query: SketchQuery, summary_input: Rc) -> Rc>) -> Rc { Rc::new(SummaryNode { expr: SummaryExpr::SummaryMerge { children }, @@ -145,22 +145,25 @@ fn merge_l4(children: Vec>) -> Rc { } fn is_sketch_agg(expr: &PhysicalExpr) -> bool { - matches!(expr, PhysicalExpr::Committed(L4Plan::Summary(n)) if matches!(n.expr, SummaryExpr::SummaryAgg { .. })) + matches!(expr, PhysicalExpr::Committed(PostAsapPlan::Summary(n)) if matches!(n.expr, SummaryExpr::SummaryAgg { .. })) } fn is_logical(expr: &PhysicalExpr) -> bool { - matches!(expr, PhysicalExpr::Committed(L4Plan::Summary(n)) if matches!(n.expr, SummaryExpr::KeepPreAsap(_))) + matches!(expr, PhysicalExpr::Committed(PostAsapPlan::Summary(n)) if matches!(n.expr, SummaryExpr::KeepPreAsap(_))) } fn is_sketch_estimate(expr: &PhysicalExpr) -> bool { - matches!(expr, PhysicalExpr::Committed(L4Plan::Summary(n)) if matches!(n.expr, SummaryExpr::SummaryEstimate { .. })) + matches!(expr, PhysicalExpr::Committed(PostAsapPlan::Summary(n)) if matches!(n.expr, SummaryExpr::SummaryEstimate { .. })) } fn is_sketch_merge(expr: &PhysicalExpr) -> bool { - matches!(expr, PhysicalExpr::Committed(L4Plan::Summary(n)) if matches!(n.expr, SummaryExpr::SummaryMerge { .. })) + matches!(expr, PhysicalExpr::Committed(PostAsapPlan::Summary(n)) if matches!(n.expr, SummaryExpr::SummaryMerge { .. })) } fn is_let_binding(expr: &PhysicalExpr) -> bool { - matches!(expr, PhysicalExpr::Committed(L4Plan::LetBinding { .. })) + matches!( + expr, + PhysicalExpr::Committed(PostAsapPlan::LetBinding { .. }) + ) } fn is_ref(expr: &PhysicalExpr) -> bool { - matches!(expr, PhysicalExpr::Committed(L4Plan::Ref { .. })) + matches!(expr, PhysicalExpr::Committed(PostAsapPlan::Ref { .. })) } /// `SummaryEstimate{Quantile{0.99}}{SummaryAgg{Kll}{Logical(Window{Scan})}}` @@ -257,9 +260,9 @@ fn allocator_let_binding_color_propagates() { // The new `SummaryEstimate::sketch_input` field is `Rc` — // upstream `asap_sketch`'s own type, which has no `Ref`/`LetBinding` // concept at all — so a `Ref`/`LetBinding` can only appear where an - // `L4Plan` is expected (this crate's own named-binding sharing + // `PostAsapPlan` is expected (this crate's own named-binding sharing // mechanism layered *above* `SummaryNode`, not inside it; see - // `physical_expr.rs`'s module docs). The property under test — + // `deployment_expr.rs`'s module docs). The property under test — // LetBinding colors by its bound expression's stage — is preserved // with the `child` position held by a bare `Ref` instead of a // `SketchEstimate{child: Ref}`. @@ -268,10 +271,10 @@ fn allocator_let_binding_color_propagates() { SketchParams::Kll { k: 200 }, logical_l4(windowed_scan()), ); - let bind = PhysicalExpr::Committed(L4Plan::LetBinding { + let bind = PhysicalExpr::Committed(PostAsapPlan::LetBinding { name: BindingName::new("kll_state"), - expr: Rc::new(L4Plan::Summary(inner_agg)), - child: Rc::new(L4Plan::Ref { + expr: Rc::new(PostAsapPlan::Summary(inner_agg)), + child: Rc::new(PostAsapPlan::Ref { name: BindingName::new("kll_state"), }), }); @@ -298,10 +301,10 @@ fn allocator_ref_resolves_to_binding_stage() { SketchParams::Kll { k: 200 }, logical_l4(windowed_scan()), ); - let bind = PhysicalExpr::Committed(L4Plan::LetBinding { + let bind = PhysicalExpr::Committed(PostAsapPlan::LetBinding { name: BindingName::new("shared"), - expr: Rc::new(L4Plan::Summary(inner_agg)), - child: Rc::new(L4Plan::Ref { + expr: Rc::new(PostAsapPlan::Summary(inner_agg)), + child: Rc::new(PostAsapPlan::Ref { name: BindingName::new("shared"), }), }); diff --git a/control_plane/src/physical/compiler.rs b/control_plane/src/physical/compiler.rs index 0186d3f8..622bcf4a 100644 --- a/control_plane/src/physical/compiler.rs +++ b/control_plane/src/physical/compiler.rs @@ -32,7 +32,7 @@ use crate::emit::monitor::MonitorIntent; use crate::physical::colored_dag::emitter::{ AggregationInput, BackendAggregation, BackendReadout, BackendStageConfig, }; -use crate::sketch_algebra::cost_model::ControlPlaneCostModel; +use crate::physical::post_asap::cost_model::ControlPlaneCostModel; use crate::types_v2::AccuracyTarget; use planner_types::pre_asap::Source; diff --git a/control_plane/src/physical/deployment_cost/sketch_capability.rs b/control_plane/src/physical/deployment_cost/sketch_capability.rs index 1334ffdb..3f9ade57 100644 --- a/control_plane/src/physical/deployment_cost/sketch_capability.rs +++ b/control_plane/src/physical/deployment_cost/sketch_capability.rs @@ -2,14 +2,14 @@ //! surface. //! //! Moved out of `physical::runtime_capability` (Stage 4 of the -//! `promql_utilities` retirement / `sketch_algebra` re-layering): this is a +//! `promql_utilities` retirement / `physical::post_asap` re-layering): this is a //! cost-model concern (insert/query throughput, memory, CPU, transmission //! size, which intents each sketch family serves), read by the optimizer //! for cost-based plan rewriting and by the physical planner to check //! whether a sketch fits within a stage's budget — it was never L4 IR, just //! filed alongside it because both modules touched `SketchAlgorithm`. //! -//! Distinct from [`crate::sketch_algebra::schema::SketchStateMetadata`] — +//! Distinct from [`crate::physical::post_asap::schema::SketchStateMetadata`] — //! that struct carries the **L4 type-system flags** (`mergeable` / //! `subtractable` / `deletable`) that gate `SketchMerge` / `SketchSubtract` //! / `SketchDelete` at plan-time. `SketchCapability` here is the diff --git a/control_plane/src/physical/deployment_cost/wire.rs b/control_plane/src/physical/deployment_cost/wire.rs index d565acbe..f4c3ad76 100644 --- a/control_plane/src/physical/deployment_cost/wire.rs +++ b/control_plane/src/physical/deployment_cost/wire.rs @@ -7,7 +7,7 @@ //! sketch runs at the edge, ships raw for backend-side sketching, or //! falls back to a Prometheus archive, based on per-workload wire-cost //! break-even math. It was fully designed and unit-tested but never -//! wired into `sketch_algebra::lower::bind_query_expr` (which always +//! wired into `physical::post_asap::lower::bind_query_expr` (which always //! produces `PhysicalExpr::Committed` — see that function's doc) or //! anywhere else; `PhysicalExpr::RawAtEdgeSketchAtBackend` / //! `RawAtEdgePrometheusArchive` remain structurally unreachable in @@ -18,7 +18,7 @@ //! //! What's left is the cost table alone — genuinely load-bearing today //! via [`WireCostTable::for_kind`], consumed by -//! `sketch_algebra::cost_model::ControlPlaneCostModel` to rank +//! `physical::post_asap::cost_model::ControlPlaneCostModel` to rank //! candidate sketch families by wire cost. //! //! ## Cost table source @@ -105,7 +105,7 @@ impl WireCostTable { /// Lookup the per-flush cost for a sketch family. /// - /// `SketchAlgorithm` (unlike the retired `sketch_algebra::SketchAlgorithm`) + /// `SketchAlgorithm` (unlike the retired `physical::post_asap::SketchAlgorithm`) /// distinguishes heap-bearing from bare frequency sketches at the /// kind level rather than via a `with_heap` param flag. This table /// never modeled the heap's extra bytes separately (the old diff --git a/control_plane/src/physical/mod.rs b/control_plane/src/physical/mod.rs index 1e759564..a544efcf 100644 --- a/control_plane/src/physical/mod.rs +++ b/control_plane/src/physical/mod.rs @@ -17,7 +17,7 @@ //! | [`plan`] | `PlanNode` / `PlanSummary` — annotated plan tree with cost estimates + stage colouring | //! | [`sketch_catalog`] | Candidate sketch types per `AggIntent`, default `SketchParams`, memory estimation | //! | [`stage_split`] | AST-aware hierarchical stage assignment (legacy `QueryExpr` splitter) | -//! | [`colored_dag`] | L5 typed colouring framework over the canonical [`crate::sketch_algebra::PhysicalExpr`] DAG (`StageId` + `Topology` + per-stage emitter) | +//! | [`colored_dag`] | L5 typed colouring framework over the canonical [`crate::physical::post_asap::PhysicalExpr`] DAG (`StageId` + `Topology` + per-stage emitter) | //! | [`topology`] | Re-exports `StageId` + `Topology` from [`colored_dag::stage_id`] — design.md §5 entry point for deployment-topology descriptors | pub mod allocator; @@ -28,6 +28,7 @@ pub mod deployment_cost; pub mod plan; pub mod plan_cache; pub mod planner; +pub mod post_asap; pub mod runtime_capability; pub mod sketch_catalog; pub mod stage_split; diff --git a/control_plane/src/sketch_algebra/cost_model.rs b/control_plane/src/physical/post_asap/cost_model.rs similarity index 99% rename from control_plane/src/sketch_algebra/cost_model.rs rename to control_plane/src/physical/post_asap/cost_model.rs index fa4d4ff5..7fe82369 100644 --- a/control_plane/src/sketch_algebra/cost_model.rs +++ b/control_plane/src/physical/post_asap/cost_model.rs @@ -109,7 +109,7 @@ impl ControlPlaneCostModel { /// [`Self::combined_eps_delta`], an `Exact` side does not bail: it /// picks the *other* side's budget (falling back to the catalog /// default `(0.01, 0.01)` only when both sides are `Exact`). Public - /// (within the crate) because [`crate::sketch_algebra::lower`]'s + /// (within the crate) because [`crate::physical::post_asap::lower`]'s /// `TopK { accuracy: Exact }` pre-pass needs the same combination. pub(crate) fn topk_eps_delta(&self, intent_accuracy: &AccuracyTarget) -> (f64, f64) { match (&self.workload_accuracy, intent_accuracy) { diff --git a/control_plane/src/sketch_algebra/physical_expr.rs b/control_plane/src/physical/post_asap/deployment_expr.rs similarity index 87% rename from control_plane/src/sketch_algebra/physical_expr.rs rename to control_plane/src/physical/post_asap/deployment_expr.rs index 7d313614..52a0a648 100644 --- a/control_plane/src/sketch_algebra/physical_expr.rs +++ b/control_plane/src/physical/post_asap/deployment_expr.rs @@ -1,13 +1,9 @@ -//! Layer 4/5 IR — `L4Plan` / `PhysicalExpr`. -//! -//! Per `control_plane/docs/design.md` §6 "`core::sketch_algebra` — Layer 4 IR" -//! and the L4/L5 layer-spine invariant: "sketch binding is already -//! committed by L4; L5 is about stage allocation + emission." +//! Backend deployment wrappers around the canonical post-ASAP plan. //! //! Step B of the plan-shaped-serving migration retires this crate's own //! `PhysicalExpr`-as-L4-algebra (the old `Logical` / `SketchAgg` / //! `SketchEstimate` / `SketchMerge` / `ExactAgg` variants) in favor of -//! ASAPController's canonical L4 IR, `planner_types::post_asap::{SummaryExpr, SummaryNode}` +//! ASAPPlanner's canonical post-ASAP IR, `planner_types::post_asap::{SummaryExpr, SummaryNode}` //! — the same move Step 3 of the enum-unification made for //! `SketchAlgorithm → SketchAlgorithm`, one layer up. `implement_promql_for_asap_tier` //! (`asap_tier_implement.rs`, Step A) already builds `Rc` trees via @@ -23,8 +19,7 @@ //! this crate discovers sharing incrementally, per-node, so it still needs //! a name to thread a bound value across sibling calls. This is a //! deployment-specific mechanism, not a fact about the sketch algebra -//! itself — L4 concern (it's still "what to compute", just with sharing), -//! hence `L4Plan` rather than `PhysicalExpr`. +//! itself, hence the backend-local [`PostAsapPlan`] wrapper. //! - **`RawAtEdgeSketchAtBackend` / `RawAtEdgePrometheusArchive`** — Phase //! ε.1's placement decisions (where the sketch gets built, not what it //! is). Genuinely L5. `physical::deployment_cost::wire` once named the same three @@ -39,7 +34,7 @@ //! don't get their own variants anymore — `planner_types::post_asap::SummaryExpr` //! already unifies all of them (including "exact accumulator" and "sketch" //! as the same `SummaryAgg` node, with or without a wrapping -//! `SummaryEstimate`) inside a single `L4Plan::Summary(Rc)`. +//! `SummaryEstimate`) inside a single `PostAsapPlan::Summary(Rc)`. #![allow(dead_code)] @@ -50,12 +45,12 @@ use planner_types::post_asap::{SketchAlgorithm, SketchParams, SummaryNode}; use crate::types_v2::BindingName; -/// L4 IR — "what to compute". Wraps `planner_types::post_asap::SummaryNode` (the sketch -/// algebra itself, owned upstream) and adds only the named-binding sharing -/// mechanism `asap_sketch` doesn't have. See module docs. +/// Backend-local wrapper around the Planner-owned post-ASAP tree. +/// +/// It adds only named sharing required during physical placement and emission. #[derive(Debug, Clone)] -pub enum L4Plan { - /// A committed L4 sub-tree — `SummaryAgg` / `SummaryEstimate` / +pub enum PostAsapPlan { + /// A committed post-ASAP sub-tree — `SummaryAgg` / `SummaryEstimate` / /// `SummaryMerge` / `Logical`, whatever `implement_tree_in_with` (or a /// deployment-specific pre-pass) produced. Summary(Rc), @@ -69,9 +64,9 @@ pub enum L4Plan { /// Binding name; must be unique within the surrounding scope. name: BindingName, /// Bound sub-expression. - expr: Rc, + expr: Rc, /// In-scope sub-tree — references the binding via `Ref`. - child: Rc, + child: Rc, }, /// Reference a `LetBinding` by name. Resolution is lexical (scope @@ -82,16 +77,17 @@ pub enum L4Plan { }, } -/// L5 IR — "where/how". Wraps an already-committed [`L4Plan`] (sketch -/// binding is final by the time anything reaches here) with placement +/// Physical placement — "where/how". Wraps an already-committed +/// [`PostAsapPlan`] (summary selection is final by the time it reaches here) +/// with placement /// info: build at the edge (the common case — `Committed` needs no extra -/// annotation since the `L4Plan` itself is the whole story), or one of +/// annotation since the `PostAsapPlan` itself is the whole story), or one of /// Phase ε.1's two backend/archive placements. #[derive(Debug, Clone)] pub enum PhysicalExpr { /// Sketch built at the edge — the default placement. The committed - /// `L4Plan` alone determines the output. - Committed(L4Plan), + /// `PostAsapPlan` alone determines the output. + Committed(PostAsapPlan), /// Phase ε.1 Mode 2: no sketch processor at the edge — raw OTLP /// forwards to the backend, which builds the sketch at ingest. The @@ -105,7 +101,7 @@ pub enum PhysicalExpr { params: SketchParams, /// Input sub-tree — typically `Summary(Logical(Window{...}))` or /// `Summary(Logical(Scan{...}))`. - child: Box, + child: Box, }, /// Phase ε.1 Mode 3: no sketch processor at the edge — raw OTLP ships @@ -140,7 +136,7 @@ impl PhysicalExpr { /// Convenience constructor for the common case: a committed /// `SummaryNode` sketch-built at the edge, no placement wrapper. pub fn committed(node: Rc) -> Self { - PhysicalExpr::Committed(L4Plan::Summary(node)) + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) } } @@ -212,7 +208,7 @@ mod tests { let node = crate::planner_selection::select_summary_default(&q).expect("implements"); let e = PhysicalExpr::committed(node); match e { - PhysicalExpr::Committed(L4Plan::Summary(node)) => match &node.expr { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => match &node.expr { planner_types::post_asap::SummaryExpr::SummaryEstimate { query, summary_input, diff --git a/control_plane/src/sketch_algebra/lower.rs b/control_plane/src/physical/post_asap/lower.rs similarity index 93% rename from control_plane/src/sketch_algebra/lower.rs rename to control_plane/src/physical/post_asap/lower.rs index e53825eb..4a3dda6f 100644 --- a/control_plane/src/sketch_algebra/lower.rs +++ b/control_plane/src/physical/post_asap/lower.rs @@ -1,7 +1,7 @@ //! L3 → L4/L5 lowering — `QueryExpr` walk that adopts //! `asap_aware_mapping::bind::implement_tree_in_with` for the sketch algebra //! itself (Step B of the plan-shaped-serving migration), with -//! `crate::sketch_algebra::cost_model::ControlPlaneCostModel` plugged in +//! `crate::physical::post_asap::cost_model::ControlPlaneCostModel` plugged in //! for family selection + parameter sizing. //! //! Per `control_plane/docs/design.md` §6: "the optimizer's job is to @@ -36,8 +36,8 @@ use std::rc::Rc; use asap_aware_mapping::cost_model::CostModel; use thiserror::Error; -use crate::sketch_algebra::cost_model::ControlPlaneCostModel; -use crate::sketch_algebra::physical_expr::{L4Plan, PhysicalExpr}; +use crate::physical::post_asap::cost_model::ControlPlaneCostModel; +use crate::physical::post_asap::deployment_expr::{PhysicalExpr, PostAsapPlan}; use crate::types_v2::AccuracyTarget; use planner_types::pre_asap::{AggIntent, QueryExpr}; @@ -82,13 +82,16 @@ pub fn bind_query_expr_with_cost_model( Ok(PhysicalExpr::Committed(bind_recursive(expr, cost_model)?)) } -fn bind_recursive(expr: &QueryExpr, cost_model: &dyn CostModel) -> Result { +fn bind_recursive( + expr: &QueryExpr, + cost_model: &dyn CostModel, +) -> Result { match expr { // `QueryExpr::LetBinding`/`::Ref` don't exist in the canonical IR // anymore (ASAPPlanner#181/#192 -- see // control_plane/docs/design-asapplanner-pin-migration.md), so // this walk can never actually receive that shape; the arms that - // used to produce `L4Plan::LetBinding`/`L4Plan::Ref` here are + // used to produce `PostAsapPlan::LetBinding`/`PostAsapPlan::Ref` here are // gone with it. // The canonical L3 IR places `TimeRange` *above* a single-statistic @@ -148,15 +151,15 @@ fn bind_recursive(expr: &QueryExpr, cost_model: &dyn CostModel) -> Result { - Ok(L4Plan::Summary(crate::planner_selection::select_summary( - expr, cost_model, - )?)) + Ok(PostAsapPlan::Summary( + crate::planner_selection::select_summary(expr, cost_model)?, + )) } _ => { let rewritten = rewrite_rate_to_increase(expr); let node = crate::planner_selection::select_summary(&rewritten, cost_model)?; - Ok(L4Plan::Summary(node)) + Ok(PostAsapPlan::Summary(node)) } } } diff --git a/control_plane/src/sketch_algebra/matcher.rs b/control_plane/src/physical/post_asap/matcher.rs similarity index 100% rename from control_plane/src/sketch_algebra/matcher.rs rename to control_plane/src/physical/post_asap/matcher.rs diff --git a/control_plane/src/physical/post_asap/mod.rs b/control_plane/src/physical/post_asap/mod.rs new file mode 100644 index 00000000..fa02f2d2 --- /dev/null +++ b/control_plane/src/physical/post_asap/mod.rs @@ -0,0 +1,22 @@ +//! Physical adapters for ASAPPlanner's canonical post-ASAP IR. +//! +//! ASAPPlanner owns summary selection and the post-ASAP `SummaryNode` tree. +//! This module adds only backend-specific concerns required to compile that +//! tree into a [`crate::backend_plan::BackendPlan`]: deployment cost input, +//! named sharing/placement wrappers, and runtime family matching. It belongs +//! under `physical`; it is not another logical or sketch-algebra layer. + +#![allow(dead_code, unused_imports)] + +pub mod cost_model; +pub mod deployment_expr; +pub mod lower; +pub mod matcher; + +#[cfg(test)] +mod tests; + +// Re-exports — `crate::physical::post_asap::*` for downstream callers. +pub use deployment_expr::{PhysicalExpr, PostAsapPlan}; +pub use lower::{bind_query_expr, bind_query_expr_with_cost_model, BindingError}; +pub use matcher::SummaryFamilyMatcher; diff --git a/control_plane/src/sketch_algebra/tests.rs b/control_plane/src/physical/post_asap/tests.rs similarity index 96% rename from control_plane/src/sketch_algebra/tests.rs rename to control_plane/src/physical/post_asap/tests.rs index cde64795..46ac6237 100644 --- a/control_plane/src/sketch_algebra/tests.rs +++ b/control_plane/src/physical/post_asap/tests.rs @@ -11,9 +11,9 @@ use planner_types::post_asap::{ }; use planner_types::pre_asap::expr_ir::ColumnRef; -use crate::sketch_algebra::cost_model::ForcedFamilyCostModel; -use crate::sketch_algebra::lower::bind_query_expr; -use crate::sketch_algebra::physical_expr::{L4Plan, PhysicalExpr}; +use crate::physical::post_asap::cost_model::ForcedFamilyCostModel; +use crate::physical::post_asap::deployment_expr::{PhysicalExpr, PostAsapPlan}; +use crate::physical::post_asap::lower::bind_query_expr; use crate::types_v2::AccuracyTarget; use planner_types::pre_asap::{AggIntent, QueryExpr, Reduction, Schema, Source}; use planner_types::pre_asap::{Column, DataType}; @@ -91,11 +91,13 @@ fn binding_is_archive(expr: &PhysicalExpr) -> bool { } } -fn plan_is_archive(plan: &L4Plan) -> bool { +fn plan_is_archive(plan: &PostAsapPlan) -> bool { match plan { - L4Plan::Summary(node) => node_is_archive(node), - L4Plan::LetBinding { expr, child, .. } => plan_is_archive(expr) || plan_is_archive(child), - L4Plan::Ref { .. } => false, + PostAsapPlan::Summary(node) => node_is_archive(node), + PostAsapPlan::LetBinding { expr, child, .. } => { + plan_is_archive(expr) || plan_is_archive(child) + } + PostAsapPlan::Ref { .. } => false, } } @@ -200,7 +202,7 @@ fn bind_picks_ddsketch_over_kll_when_eps_explicit() { let bound = bind_query_expr(&expr, AccuracyTarget::Epsilon(0.01)) .expect("bind_query_expr should not error"); match bound { - PhysicalExpr::Committed(L4Plan::Summary(node)) => match &node.expr { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => match &node.expr { SummaryExpr::SummaryEstimate { summary_input, .. } => match &summary_input.expr { SummaryExpr::SummaryAgg { family, .. } => { assert!( @@ -236,7 +238,7 @@ fn agg_topk(k: usize, accuracy: AccuracyTarget) -> QueryExpr { /// return anymore. fn topk_binding_family(bound: &PhysicalExpr) -> (SketchAlgorithm, u32, u32) { match bound { - PhysicalExpr::Committed(L4Plan::Summary(node)) => match &node.expr { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => match &node.expr { SummaryExpr::SummaryEstimate { query, summary_input, @@ -351,7 +353,7 @@ fn bind_hll_cardinality_basic() { }; let bound = bind_query_expr(&expr, AccuracyTarget::Epsilon(0.01)).expect("no error"); match bound { - PhysicalExpr::Committed(L4Plan::Summary(node)) => match &node.expr { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => match &node.expr { SummaryExpr::SummaryEstimate { query, summary_input, @@ -390,7 +392,7 @@ fn sum_now_binds_to_exact_agg_after_pr_6_followup() { // variant (and `asap_types::AggregationType`) no longer exist at // the L4 IR level: `planner_types::post_asap::SummaryExpr` unifies exact // accumulators and approximate sketches into the same `SummaryAgg` - // node shape, keyed by `SummaryKind` (see `physical_expr.rs`'s + // node shape, keyed by `SummaryKind` (see `deployment_expr.rs`'s // module docs). let expr = QueryExpr::Aggregate { reduction: Reduction::PerEntity, @@ -401,7 +403,7 @@ fn sum_now_binds_to_exact_agg_after_pr_6_followup() { }; let bound = bind_query_expr(&expr, AccuracyTarget::Exact).expect("no error"); match bound { - PhysicalExpr::Committed(L4Plan::Summary(node)) => match &node.expr { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => match &node.expr { SummaryExpr::SummaryAgg { family, .. } => { assert_eq!( family, @@ -423,7 +425,7 @@ fn bind_exact_accuracy_disables_quantile_binding() { let expr = agg_quantile(0.99, AccuracyTarget::Exact); let bound = bind_query_expr(&expr, AccuracyTarget::Exact).expect("no error"); match bound { - PhysicalExpr::Committed(L4Plan::Summary(node)) => { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => { assert!( matches!(&node.expr, SummaryExpr::KeepPreAsap(qe) if matches!(**qe, QueryExpr::Aggregate { .. })), "Exact accuracy should disable summary binding and pass through as Logical, got {:?}", @@ -460,7 +462,7 @@ fn phase_b_pattern_only_temporal_quantile_binds_to_sketch() { }; let bound = bind_query_expr(&expr, AccuracyTarget::Epsilon(0.01)).unwrap(); match bound { - PhysicalExpr::Committed(L4Plan::Summary(node)) => match &node.expr { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => match &node.expr { SummaryExpr::SummaryEstimate { query, summary_input, @@ -501,7 +503,7 @@ fn phase_b_pattern_only_temporal_sum_binds_to_exact_agg() { }; let bound = bind_query_expr(&expr, AccuracyTarget::Epsilon(0.01)).unwrap(); match bound { - PhysicalExpr::Committed(L4Plan::Summary(node)) => match &node.expr { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => match &node.expr { SummaryExpr::SummaryAgg { family, .. } => { assert_eq!( family, @@ -533,7 +535,7 @@ fn phase_b_pattern_only_spatial_aggregate_binds_to_multiple_sum() { }; let bound = bind_query_expr(&expr, AccuracyTarget::Epsilon(0.01)).unwrap(); match bound { - PhysicalExpr::Committed(L4Plan::Summary(node)) => match &node.expr { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => match &node.expr { SummaryExpr::SummaryAgg { family, reduction, .. } => { @@ -571,7 +573,7 @@ fn phase_b_pattern_temporal_and_spatial_combined_binds_to_multiple_increase() { }; let bound = bind_query_expr(&expr, AccuracyTarget::Epsilon(0.01)).unwrap(); match bound { - PhysicalExpr::Committed(L4Plan::Summary(node)) => match &node.expr { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => match &node.expr { SummaryExpr::SummaryAgg { family, reduction, .. } => { @@ -616,7 +618,7 @@ fn phase_b_pattern_archive_only_routes_to_archive() { // The archive-only rule's output is a Logical pass-through carrying // the original Aggregate. Downstream emitters check archive_only(). match bound { - PhysicalExpr::Committed(L4Plan::Summary(node)) => match &node.expr { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => match &node.expr { SummaryExpr::KeepPreAsap(qe) => match qe.as_ref() { QueryExpr::Aggregate { measures: aggs, .. } => { assert_eq!(aggs, &vec![intent]); @@ -841,7 +843,7 @@ fn phase_b_archive_only_intents_round_trip_through_binder() { let bound = bind_query_expr(&expr, AccuracyTarget::Epsilon(0.01)).expect("bind should succeed"); match bound { - PhysicalExpr::Committed(L4Plan::Summary(node)) => match &node.expr { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => match &node.expr { SummaryExpr::KeepPreAsap(qe) => match qe.as_ref() { QueryExpr::Aggregate { measures: aggs, .. } => { assert_eq!(aggs.len(), 1); @@ -888,7 +890,7 @@ fn frequency_extension_binds_cms() { }; let bound = bind_query_expr(&expr, AccuracyTarget::Epsilon(0.01)).expect("no error"); match bound { - PhysicalExpr::Committed(L4Plan::Summary(node)) => { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => { let SummaryExpr::SummaryEstimate { summary_input, query, @@ -928,7 +930,7 @@ fn topk_exact_accuracy_declines_to_bind() { let expr = agg_topk(10, AccuracyTarget::Exact); let bound = bind_query_expr(&expr, AccuracyTarget::Exact).expect("no error"); match bound { - PhysicalExpr::Committed(L4Plan::Summary(node)) => { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => { assert!( matches!(&node.expr, SummaryExpr::KeepPreAsap(_)), "TopK{{accuracy: Exact}} should decline pending ASAPController#151, got {:?}", diff --git a/control_plane/src/physical/runtime_capability.rs b/control_plane/src/physical/runtime_capability.rs index 9f5e6de8..30225cea 100644 --- a/control_plane/src/physical/runtime_capability.rs +++ b/control_plane/src/physical/runtime_capability.rs @@ -5,7 +5,7 @@ //! cost-model half of that consolidation — [`SketchCapability`] / //! `SupportedIntent` / `default_capability_table` / `load_capability_overrides` //! — moved to `crate::physical::deployment_cost::sketch_capability` (Stage 4 of the -//! `sketch_algebra` re-layering): it's a cost-model concern read by the +//! `physical::post_asap` re-layering): it's a cost-model concern read by the //! optimizer and physical planner, not L4 IR. What's left here: //! //! - [`Capability`] / [`SketchKindHandle`] — query-side capability tag, @@ -19,7 +19,7 @@ #![allow(dead_code)] -use crate::sketch_algebra::matcher::sketch_family_satisfied; +use crate::physical::post_asap::matcher::sketch_family_satisfied; use crate::types_v2::AccuracyTarget; use asap_types::AggregationType; use planner_types::post_asap::SketchAlgorithm; @@ -1067,7 +1067,7 @@ mod tests { assert!(required_concrete.is_satisfied_by(&cap)); // Intentional broadening vs. this module's pre-`sketch_family_satisfied` // behavior: CMS and CountSketch are the SAME frequency family in - // `sketch_algebra::matcher`'s reference rule table (both bare and + // `physical::post_asap::matcher`'s reference rule table (both bare and // heap-bearing — see its // `cms_and_count_sketch_are_the_same_frequency_family` test), so a // `CmsWithHeap` requirement IS now satisfied by a diff --git a/control_plane/src/physical/stage_split.rs b/control_plane/src/physical/stage_split.rs index d3039574..f1322958 100644 --- a/control_plane/src/physical/stage_split.rs +++ b/control_plane/src/physical/stage_split.rs @@ -1,7 +1,7 @@ //! L5 stage split — assign the L4 `PhysicalExpr` DAG across pipeline stages. //! //! The control plane's L5: take the sketch-bound `PhysicalExpr` produced -//! by `sketch_algebra::bind_query_expr`, colour its DAG by `StageId` +//! by `physical::post_asap::bind_query_expr`, colour its DAG by `StageId` //! across the DC three-stage topology (`crate::physical::colored_dag:: //! StageAllocator` + `ThreeStageEmitter`), and return one //! `StageConfig` per stage for the per-stage emitters in @@ -12,7 +12,7 @@ //! retired; `split_typed_three_stage` below is the sole L5. /// Env-var that opts *out* of the typed L5 stage_split path. The typed -/// path — `sketch_algebra::PhysicalExpr` (L4) → `split_typed_three_stage` +/// path — `physical::post_asap::PhysicalExpr` (L4) → `split_typed_three_stage` /// → per-stage `StageConfig` emit — is the primary (and only) L5; this /// var exists only as a kill switch. #[allow(dead_code)] @@ -42,7 +42,7 @@ pub fn typed_stage_split_enabled() -> bool { /// `emit_gateway_yaml` for `Gateway`, `emit_backend_streaming_config_json` /// for `Backend`. pub fn split_typed_three_stage( - expr: &crate::sketch_algebra::PhysicalExpr, + expr: &crate::physical::post_asap::PhysicalExpr, ) -> Option< std::collections::HashMap< crate::physical::colored_dag::StageId, @@ -102,9 +102,9 @@ mod l5_walk_propagation_tests { #[test] fn l5_walk_surfaces_metric_name_for_bind_workload_typed_output() { let w = workload("http_latency_ms", Vec::new(), Duration::from_secs(60)); - let physical_expr = + let deployment_expr = crate::physical::workload_planner::bind_workload_typed(&w).expect("bind produced expr"); - let configs = super::split_typed_three_stage(&physical_expr).expect("split ok"); + let configs = super::split_typed_three_stage(&deployment_expr).expect("split ok"); let backend_cfg = configs .into_values() .find_map(|cfg| match cfg { @@ -126,9 +126,9 @@ mod l5_walk_propagation_tests { #[test] fn l5_walk_surfaces_window_secs_for_bind_workload_typed_output() { let w = workload("http_latency_ms", Vec::new(), Duration::from_secs(120)); - let physical_expr = + let deployment_expr = crate::physical::workload_planner::bind_workload_typed(&w).expect("bind produced expr"); - let configs = super::split_typed_three_stage(&physical_expr).expect("split ok"); + let configs = super::split_typed_three_stage(&deployment_expr).expect("split ok"); let backend_cfg = configs .into_values() .find_map(|cfg| match cfg { @@ -161,9 +161,9 @@ mod l5_walk_propagation_tests { vec!["zone".to_string()], Duration::from_secs(60), ); - let physical_expr = + let deployment_expr = crate::physical::workload_planner::bind_workload_typed(&w).expect("bind produced expr"); - let configs = super::split_typed_three_stage(&physical_expr).expect("split ok"); + let configs = super::split_typed_three_stage(&deployment_expr).expect("split ok"); let backend_cfg = configs .into_values() .find_map(|cfg| match cfg { diff --git a/control_plane/src/physical/workload_planner.rs b/control_plane/src/physical/workload_planner.rs index 777532e2..065273fb 100644 --- a/control_plane/src/physical/workload_planner.rs +++ b/control_plane/src/physical/workload_planner.rs @@ -36,7 +36,7 @@ fn mvp_deployment_policy( }) } -/// Bind a `QueryWorkload` into the typed L4 [`crate::sketch_algebra::PhysicalExpr`] +/// Bind a `QueryWorkload` into the typed L4 [`crate::physical::post_asap::PhysicalExpr`] /// IR, when callers want to inspect the typed binding alongside the /// legacy `CollectionPlan` output. /// @@ -69,7 +69,7 @@ fn mvp_deployment_policy( /// the parallel `USE_TYPED_STAGE_SPLIT` gate is enabled — the bound /// `PhysicalExpr` is then fed into `planner::stage_split::split_typed_three_stage` /// + the per-stage emitters in `config::stage_config`. -pub fn bind_workload_typed(w: &QueryWorkload) -> Option { +pub fn bind_workload_typed(w: &QueryWorkload) -> Option { bind_workload_typed_with_item_filter(w, None) } @@ -87,8 +87,8 @@ pub fn bind_workload_typed(w: &QueryWorkload) -> Option, -) -> Option { - use crate::sketch_algebra::cost_model::ForcedFamilyCostModel; +) -> Option { + use crate::physical::post_asap::cost_model::ForcedFamilyCostModel; use crate::types_v2::AccuracyTarget; use planner_types::post_asap::SketchAlgorithm; use planner_types::pre_asap::{AggIntent as L3AggIntent, QueryExpr, Schema, Source}; @@ -286,7 +286,7 @@ pub fn bind_workload_typed_with_item_filter( ) { return None; } - Some(crate::sketch_algebra::physical_expr::PhysicalExpr::committed(node)) + Some(crate::physical::post_asap::deployment_expr::PhysicalExpr::committed(node)) } pub struct DeploymentPlanCompiler { @@ -611,7 +611,7 @@ mod tests { // | `top_endpoint_qps` | CountSketch | // | `endpoint_request_freq` | CMS | - use crate::sketch_algebra::physical_expr::PhysicalExpr; + use crate::physical::post_asap::deployment_expr::PhysicalExpr; use planner_types::post_asap::SketchAlgorithm; use planner_types::pre_asap::expr_ir::ColumnRef; @@ -628,8 +628,9 @@ mod tests { /// readout itself (to check `PointCount`'s `key`/`value`), not just /// the sketch family underneath it. fn extract_query(expr: &PhysicalExpr) -> Option { - let PhysicalExpr::Committed(crate::sketch_algebra::physical_expr::L4Plan::Summary(node)) = - expr + let PhysicalExpr::Committed( + crate::physical::post_asap::deployment_expr::PostAsapPlan::Summary(node), + ) = expr else { return None; }; diff --git a/control_plane/src/replan.rs b/control_plane/src/replan.rs index 38cfd852..9f72af60 100644 --- a/control_plane/src/replan.rs +++ b/control_plane/src/replan.rs @@ -203,7 +203,7 @@ impl Replanner { /// /// Steps: /// 1. `bind_workload_typed(&workload)` → PhysicalExpr - /// 2. `split_typed_three_stage(&physical_expr)` → per-stage configs + /// 2. `split_typed_three_stage(&deployment_expr)` → per-stage configs /// 3. Pick the `Edge` stage config /// 4. Apply `extend_edge_with_demo_plumbing` (freshness probes + /// workload-registry archive metrics) so the OpAMP-pushed YAML @@ -242,8 +242,8 @@ impl Replanner { workload: &QueryWorkload, agent_id: &str, ) -> Option { - let physical_expr = rules::bind_workload_typed(workload)?; - let configs = stage_split::split_typed_three_stage(&physical_expr)?; + let deployment_expr = rules::bind_workload_typed(workload)?; + let configs = stage_split::split_typed_three_stage(&deployment_expr)?; let mut edge_cfg = configs.into_iter().find_map(|(_, cfg)| match cfg { crate::physical::colored_dag::StageConfig::Edge(edge) => Some(edge), _ => None, @@ -600,8 +600,8 @@ impl Replanner { role: AggRole, ) -> Option { // ── Typed sketch path (Quantile / Cardinality / TopK / Frequency) ── - if let Some(physical_expr) = rules::bind_workload_typed(workload) { - if let Some(configs) = stage_split::split_typed_three_stage(&physical_expr) { + if let Some(deployment_expr) = rules::bind_workload_typed(workload) { + if let Some(configs) = stage_split::split_typed_three_stage(&deployment_expr) { if let Some(mut be) = configs.into_iter().find_map(|(_, cfg)| match cfg { crate::physical::colored_dag::StageConfig::Backend(be) => Some(be), _ => None, diff --git a/control_plane/src/sketch_algebra/mod.rs b/control_plane/src/sketch_algebra/mod.rs deleted file mode 100644 index 5465286e..00000000 --- a/control_plane/src/sketch_algebra/mod.rs +++ /dev/null @@ -1,43 +0,0 @@ -//! Layer 4 IR — `core::sketch_algebra` per `control_plane/docs/design.md` §6. -//! -//! Phase C introduces the L4 vocabulary the planner pivots on: -//! -//! - [`PhysicalExpr`] — the L4 algebra DAG (sketch-bound, language-orthogonal, -//! deployment-independent). Single-rooted per query; multi-root -//! workload-level fan-in lives one layer up in -//! `types_v2::WorkloadPlan`. -//! - `planner_types::post_asap::SummaryKind` / `SummaryParams` — typed sketch-family -//! selector + parameter payload (moved out of this crate — formerly -//! `sketch_params::SketchKind`/`SketchParams` — Stage 3 of the -//! sketch-identity unification; see -//! `scratchpad/artifacts/enum-unification-plan.md`). -//! - [`bind_query_expr`] — the L3→L4 lowering driver: bottom-up walk -//! that delegates to `asap_aware_mapping::bind::implement_tree_in_with` (the -//! local `Bind*` rule family it used to fire was retired in Step B). -//! -//! Scope reduction (per orchestrator spec): the variant set ships the -//! subset DC + PromQL needs. `SketchJoin`, `SketchSubtract`, -//! `SketchDelete` from design.md §6 are intentionally *not* surfaced -//! yet — they're gated on rules that haven't landed. Adding them is -//! purely additive. -//! -//! Wire-up state. `bind_query_expr` runs unconditionally from `main.rs` -//! — there is no env-gate on this L3→L4 binding step itself. The one env -//! var in this area, `USE_TYPED_STAGE_SPLIT` -//! (`physical::stage_split::ENV_USE_TYPED_STAGE_SPLIT`), gates the -//! *downstream* L4→L5 stage-split step, not this module. - -#![allow(dead_code, unused_imports)] - -pub mod cost_model; -pub mod lower; -pub mod matcher; -pub mod physical_expr; - -#[cfg(test)] -mod tests; - -// Re-exports — `crate::sketch_algebra::*` for downstream callers. -pub use lower::{bind_query_expr, bind_query_expr_with_cost_model, BindingError}; -pub use matcher::SummaryFamilyMatcher; -pub use physical_expr::{L4Plan, PhysicalExpr}; diff --git a/control_plane/src/sketch_selection.rs b/control_plane/src/sketch_selection.rs index d3e8fed0..8030c5c3 100644 --- a/control_plane/src/sketch_selection.rs +++ b/control_plane/src/sketch_selection.rs @@ -19,7 +19,7 @@ //! When a capability binds a *concrete* `SketchKindHandle` (not `Any`), the //! result is exactly that one family; `Any` expands to the full candidate set. //! -//! Moved out of `sketch_algebra` (Stage 4 of the `sketch_algebra` +//! Moved out of `physical::post_asap` (Stage 4 of the `physical::post_asap` //! re-layering) — this is a query-planning concern (its one caller is //! [`crate::query_planning`]), not L4 IR. diff --git a/control_plane/src/types.rs b/control_plane/src/types.rs index 69e1d145..81b9de7b 100644 --- a/control_plane/src/types.rs +++ b/control_plane/src/types.rs @@ -194,9 +194,9 @@ impl std::fmt::Display for SketchType { } } -// Moved from the retired `sketch_algebra::sketch_params` (Stage 3 of the +// Moved from the retired `physical::post_asap::sketch_params` (Stage 3 of the // sketch-identity unification — see -// scratchpad/artifacts/enum-unification-plan.md) when `sketch_algebra::SketchAlgorithm` +// scratchpad/artifacts/enum-unification-plan.md) when `physical::post_asap::SketchAlgorithm` // was replaced by `planner_types::post_asap::SummaryKind` (later `planner_types::post_asap:: // SketchAlgorithm` once ASAPPlanner split the old flat `SummaryKind` per-family — // see control_plane/docs/design-asapplanner-pin-migration.md). `SketchType:: diff --git a/data_plane/src/query_engines/asap_query_engine/post_asap_planner.rs b/data_plane/src/query_engines/asap_query_engine/post_asap_planner.rs index 9430386e..6f876c53 100644 --- a/data_plane/src/query_engines/asap_query_engine/post_asap_planner.rs +++ b/data_plane/src/query_engines/asap_query_engine/post_asap_planner.rs @@ -40,11 +40,11 @@ use std::rc::Rc; use planner_types::post_asap::{SketchAlgorithm, SketchParams, SummaryExpr, SummaryNode}; -use control_plane::physical::runtime_capability::{OuterFn, SketchKindHandle}; -use control_plane::sketch_algebra::cost_model::ObservedFamilyCostModel; -use control_plane::sketch_algebra::{ - bind_query_expr_with_cost_model, BindingError, L4Plan, PhysicalExpr, +use control_plane::physical::post_asap::cost_model::ObservedFamilyCostModel; +use control_plane::physical::post_asap::{ + bind_query_expr_with_cost_model, BindingError, PhysicalExpr, PostAsapPlan, }; +use control_plane::physical::runtime_capability::{OuterFn, SketchKindHandle}; use control_plane::types_v2::AccuracyTarget; use crate::query_engines::asap_query_engine::summary_executor::find_metric_in_query_expr; @@ -107,7 +107,7 @@ pub enum LoweringSkip { ExecuteFailed(String), } -// `L4Plan` and `PhysicalExpr` are backend compatibility/placement wrappers. +// `PostAsapPlan` and `PhysicalExpr` are backend compatibility/placement wrappers. // The semantic tree returned by ASAPPlanner is `post_asap::SummaryNode`; this // module does not claim or recreate an ASAPPlanner "L4" IR. @@ -359,7 +359,7 @@ pub fn plan_promql_to_post_asap( .map_err(|e: BindingError| LoweringSkip::Implement(e.to_string()))?; match physical { - PhysicalExpr::Committed(L4Plan::Summary(node)) => { + PhysicalExpr::Committed(PostAsapPlan::Summary(node)) => { if matches!(node.expr, SummaryExpr::KeepPreAsap(_)) { Err(LoweringSkip::NotRealized) } else { diff --git a/data_plane/tests/e2e_controller_plans_and_backend_serves.rs b/data_plane/tests/e2e_controller_plans_and_backend_serves.rs index 8898c4e0..cd828744 100644 --- a/data_plane/tests/e2e_controller_plans_and_backend_serves.rs +++ b/data_plane/tests/e2e_controller_plans_and_backend_serves.rs @@ -117,9 +117,9 @@ fn build_workload( fn plan_backend_stage_config( workload: &QueryWorkload, ) -> control_plane::physical::colored_dag::BackendStageConfig { - let physical_expr = control_plane::physical::workload_planner::bind_workload_typed(workload) + let deployment_expr = control_plane::physical::workload_planner::bind_workload_typed(workload) .expect("bind_workload_typed produced a PhysicalExpr"); - let configs = control_plane::physical::stage_split::split_typed_three_stage(&physical_expr) + let configs = control_plane::physical::stage_split::split_typed_three_stage(&deployment_expr) .expect("split_typed_three_stage produced per-stage configs"); let mut backend_cfg = configs .into_iter()