Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
138 commits
Select commit Hold shift + click to select a range
ac30f32
docs: clarify Planner physical plan and SDS architecture
zzylol Sep 17, 2026
af61296
docs: specify executable subplan materialization boundaries
zzylol Sep 18, 2026
e868424
docs: scope migration to backend precompute and query plans
zzylol Sep 18, 2026
daa5281
docs: clarify window terminology migration
zzylol Sep 18, 2026
e27bbb0
Revert "docs: clarify window terminology migration"
zzylol Sep 18, 2026
2230795
docs: focus physical plan and SDS designs
zzylol Sep 18, 2026
3f1830d
docs: add physical compiler input example
zzylol Sep 18, 2026
dd0a8b4
docs: add physical compiler output example
zzylol Sep 18, 2026
c1fbfb6
docs: include query expression in compiler example
zzylol Sep 18, 2026
887c526
docs: reorganize physical plan integration design
zzylol Sep 18, 2026
b8193bb
docs: reorganize SDS and migration designs
zzylol Sep 18, 2026
b24867b
docs: define maintenance inputs before plan split example
zzylol Sep 18, 2026
b358074
docs: use plan version consistently in backend design
zzylol Sep 18, 2026
7e4655a
docs: remove standalone catalog materialization abstraction
zzylol Sep 18, 2026
07580f8
docs: add concise planner backend glossary
zzylol Sep 18, 2026
f6d9cb3
refactor: split installed maintenance DAGs from query execution
zzylol Sep 19, 2026
9713cbc
refactor: remove backend Collector dependency and normalize legacy DAGs
zzylol Sep 19, 2026
7ee09b6
test: restore whole-backend process coverage without Collector
zzylol Sep 19, 2026
cf1b344
fix: migrate Planner main and reject legacy runtime artifacts
zzylol Sep 21, 2026
5d1519d
Merge remote-tracking branch 'origin/main' into refactor/backend-plan…
zzylol Sep 21, 2026
f611bf5
test: send full sketch envelope in whole-backend E2E
zzylol Sep 21, 2026
36b4f10
refactor: bind backend summary state through versioned SDS slots
zzylol Sep 21, 2026
6d04b15
test: send complete sketch envelopes in process fixtures
zzylol Sep 21, 2026
ac855b2
docs: clarify selected deployment guarantee terminology
zzylol Sep 21, 2026
ea3226c
docs: explain missing planner maintenance guarantee
zzylol Sep 21, 2026
118e363
docs: motivate selected producer maintenance decision
zzylol Sep 21, 2026
1effeb5
docs: label catalog reads and SDS metadata ownership
zzylol Sep 21, 2026
ddc50e2
docs: align SDS ownership and lifecycle terminology
zzylol Sep 21, 2026
8e6d244
Merge main into docs design proposal
zzylol Sep 21, 2026
3c273ed
docs: use current planner and plan-version names consistently
zzylol Sep 21, 2026
1f0b4df
docs: align integration diagram with SDS ownership
zzylol Sep 21, 2026
5ceefb7
docs: clarify instance identity and shared producer wording
zzylol Sep 21, 2026
cc0e41b
Merge design docs and current main into backend plan split
zzylol Sep 21, 2026
7d9faff
refactor: align plan bindings with current Planner and SDS contract
zzylol Sep 22, 2026
32de737
docs: distinguish summary definitions from runtime stores
zzylol Sep 22, 2026
be97173
docs: model one runtime summary store for DAG bindings
zzylol Sep 22, 2026
71157f4
docs: scope SDS lifecycle to read eligibility
zzylol Sep 22, 2026
d9fff69
docs: tie stored summary examples directly to DAG outputs
zzylol Sep 22, 2026
00e68cd
docs: name summary tables, stored records, and output references by role
zzylol Sep 22, 2026
073daa2
docs: illustrate summary definitions, stored records, and output refe…
zzylol Sep 22, 2026
edaf750
docs: limit v1 summary storage to definitions and stored summaries
zzylol Sep 22, 2026
306859c
Merge remote-tracking branch 'origin/docs/physical-plan-design' into …
zzylol Sep 22, 2026
01258d9
refactor: align plan bindings with summary store v1
zzylol Sep 22, 2026
f1a9a51
fix: validate selected DAG provenance
zzylol Sep 22, 2026
55e4780
Merge remote-tracking branch 'origin/main' into stack/requested-737
zzylol Sep 22, 2026
571dc70
merge: stack PR 749 on current PR 737 and main
zzylol Sep 22, 2026
c2ac090
fix: retain neutral sketch codec dependencies when syncing main
zzylol Sep 22, 2026
a0bf688
fix: align derived DAG validation with current schema versions
zzylol Sep 22, 2026
5c8b489
fix: keep maintenance document version distinct from complete DAG ver…
zzylol Sep 22, 2026
7d19dff
refactor: adopt costed Planner selection without legacy API adapters
zzylol Sep 23, 2026
ee71eca
Merge Planner selection baseline and require migration without legacy…
zzylol Sep 23, 2026
697a69e
Merge current Planner API baseline into split backend plans
zzylol Sep 23, 2026
69f6210
test: verify exact process routing for uncertified Planner candidates
zzylol Sep 23, 2026
61a4a3c
Merge branch 'refactor/planner-selection-api' into stack/planner-api-737
zzylol Sep 23, 2026
2e41f80
Merge branch 'stack/planner-api-737' into stack/planner-api-749
zzylol Sep 23, 2026
0eefb49
docs: remove redundant Planner selection contract
zzylol Sep 23, 2026
48e9950
Merge branch 'stack/planner-api-737' into stack/planner-api-749
zzylol Sep 23, 2026
5ed60fc
Merge branch 'refactor/planner-selection-api' into stack/planner-api-737
zzylol Sep 23, 2026
d389e3b
deps: pin Planner bounded HLL confidence model
zzylol Sep 23, 2026
7c3d80a
test: size transmitted KLL state from a certified accuracy contract
zzylol Sep 23, 2026
5dc0113
Merge branch 'stack/planner-api-737' into stack/planner-api-749
zzylol Sep 23, 2026
61e0c14
Merge branch 'refactor/planner-selection-api' into stack/planner-api-737
zzylol Sep 23, 2026
67e8f13
test: retain KLL collector capability when using theoretical confidence
zzylol Sep 23, 2026
af35131
refactor: implement typed summary semantics and physical plan lowering
zzylol Sep 24, 2026
67e9cb9
docs: separate Planner physical computation from backend deployment
zzylol Sep 25, 2026
09e1bad
Merge branch 'integration/physical-stack-737' into integration/physic…
zzylol Sep 25, 2026
985b3cc
refactor: name the backend orchestration entry DeploymentPlanCompiler
zzylol Sep 25, 2026
ae604d0
Merge branch 'integration/physical-stack-749' into integration/physic…
zzylol Sep 25, 2026
858c9ba
docs: bind Planner physical DAGs without backend re-lowering
zzylol Sep 26, 2026
5bb4d70
docs: describe summary inputs with groups and pane duration
zzylol Sep 26, 2026
20b2d39
docs: define summary semantic completeness beyond input scope
zzylol Sep 26, 2026
b49e47a
docs: define SDS identity through canonical Planner computation
zzylol Sep 26, 2026
fb07b89
docs: decouple SDS semantic identity from executable Planner IR
zzylol Sep 26, 2026
134db0c
docs: define Planner-owned SDS discovery for future ad hoc queries
zzylol Sep 26, 2026
7367cc4
docs: streamline SDS design around definitions and stored results
zzylol Sep 26, 2026
b3163ef
docs: track bound-query SDS migration across implementation PRs
zzylol Sep 26, 2026
b38ae64
Merge remote-tracking branch 'sds-review/737' into impl/sds-semantic-…
zzylol Sep 26, 2026
199cc76
Merge branch 'impl/sds-semantic-identity' into impl/sds-stack-771
zzylol Sep 26, 2026
53bfb2f
docs: identify active shared-library PR in bound-query migration
zzylol Sep 26, 2026
57705f6
Merge branch 'docs/pr737-design-boundaries' into impl/sds-semantic-id…
zzylol Sep 26, 2026
41eb1e2
Merge branch 'impl/sds-semantic-identity' into impl/sds-stack-771
zzylol Sep 26, 2026
39cf8d8
docs: separate bound SDS range lookup from state validation
zzylol Sep 26, 2026
534546c
Merge branch 'docs/pr737-design-boundaries' into impl/sds-semantic-id…
zzylol Sep 26, 2026
861bd11
Merge branch 'impl/sds-semantic-identity' into impl/sds-stack-771
zzylol Sep 26, 2026
b0d77ce
docs: state SDS migration responsibilities without stale implementati…
zzylol Sep 26, 2026
fd3a02a
Merge branch 'docs/pr737-design-boundaries' into impl/sds-semantic-id…
zzylol Sep 26, 2026
cb1e237
Merge branch 'impl/sds-semantic-identity' into impl/sds-stack-771
zzylol Sep 26, 2026
749252d
docs: clarify Planner physical plan and SDS architecture
zzylol Sep 17, 2026
74255ec
docs: specify executable subplan materialization boundaries
zzylol Sep 18, 2026
d048262
docs: scope migration to backend precompute and query plans
zzylol Sep 18, 2026
ae92339
docs: clarify window terminology migration
zzylol Sep 18, 2026
d25d6c9
Revert "docs: clarify window terminology migration"
zzylol Sep 18, 2026
011a6cd
docs: focus physical plan and SDS designs
zzylol Sep 18, 2026
1ca64ed
docs: add physical compiler input example
zzylol Sep 18, 2026
06b26eb
docs: add physical compiler output example
zzylol Sep 18, 2026
9a1c41b
docs: include query expression in compiler example
zzylol Sep 18, 2026
19bc7da
docs: reorganize physical plan integration design
zzylol Sep 18, 2026
8fbe0f3
docs: reorganize SDS and migration designs
zzylol Sep 18, 2026
eb3c3c4
docs: define maintenance inputs before plan split example
zzylol Sep 18, 2026
c9b6ea7
docs: use plan version consistently in backend design
zzylol Sep 18, 2026
4de2df4
docs: remove standalone catalog materialization abstraction
zzylol Sep 18, 2026
9892bed
docs: add concise planner backend glossary
zzylol Sep 18, 2026
1232ce9
docs: clarify selected deployment guarantee terminology
zzylol Sep 21, 2026
158c22a
docs: explain missing planner maintenance guarantee
zzylol Sep 21, 2026
6322175
docs: motivate selected producer maintenance decision
zzylol Sep 21, 2026
8bdb7a7
docs: label catalog reads and SDS metadata ownership
zzylol Sep 21, 2026
813e3e3
docs: align SDS ownership and lifecycle terminology
zzylol Sep 21, 2026
f3bd9d8
docs: use current planner and plan-version names consistently
zzylol Sep 21, 2026
11e21d2
docs: align integration diagram with SDS ownership
zzylol Sep 21, 2026
b4dec9b
docs: clarify instance identity and shared producer wording
zzylol Sep 21, 2026
f300704
docs: distinguish summary definitions from runtime stores
zzylol Sep 22, 2026
520ace6
docs: model one runtime summary store for DAG bindings
zzylol Sep 22, 2026
864c2a2
docs: scope SDS lifecycle to read eligibility
zzylol Sep 22, 2026
e0ab398
docs: tie stored summary examples directly to DAG outputs
zzylol Sep 22, 2026
5f383d1
docs: name summary tables, stored records, and output references by role
zzylol Sep 22, 2026
a2ab168
docs: illustrate summary definitions, stored records, and output refe…
zzylol Sep 22, 2026
d5f5203
docs: limit v1 summary storage to definitions and stored summaries
zzylol Sep 22, 2026
ebf4569
docs: separate Planner physical computation from backend deployment
zzylol Sep 25, 2026
eb60220
docs: bind Planner physical DAGs without backend re-lowering
zzylol Sep 26, 2026
1b36bb7
docs: describe summary inputs with groups and pane duration
zzylol Sep 26, 2026
b12512f
docs: define summary semantic completeness beyond input scope
zzylol Sep 26, 2026
51185de
docs: define SDS identity through canonical Planner computation
zzylol Sep 26, 2026
69b28c2
docs: decouple SDS semantic identity from executable Planner IR
zzylol Sep 26, 2026
5ffc426
docs: define Planner-owned SDS discovery for future ad hoc queries
zzylol Sep 26, 2026
5bcd54c
docs: streamline SDS design around definitions and stored results
zzylol Sep 26, 2026
5b402b8
docs: track bound-query SDS migration across implementation PRs
zzylol Sep 26, 2026
0d9ab8e
docs: identify active shared-library PR in bound-query migration
zzylol Sep 26, 2026
ef6c127
docs: separate bound SDS range lookup from state validation
zzylol Sep 26, 2026
eb94d73
docs: state SDS migration responsibilities without stale implementati…
zzylol Sep 26, 2026
5f1eebf
docs: preserve design index after rebasing onto main
zzylol Sep 28, 2026
8857f25
docs: clarify SDS source identity and version-scoped recovery
zzylol Sep 28, 2026
bccb189
docs: illustrate SDS identity and recovery decisions
zzylol Sep 28, 2026
12896bd
Merge branch 'restack/pr737-main' into impl/sds-semantic-identity
zzylol Sep 28, 2026
bc417b0
Merge branch 'impl/sds-semantic-identity' into impl/sds-stack-771
zzylol Sep 28, 2026
6e3a50b
merge: base typed plan support on rebased foundation
zzylol Sep 28, 2026
5d6cdbc
Merge branch 'restack/pr749-main' into impl/sds-stack-771
zzylol Sep 28, 2026
2dbe763
Merge branch 'restack/pr749-main' into impl/sds-stack-771
zzylol Sep 28, 2026
38fb552
Merge branch 'restack/pr749-main' into impl/sds-stack-771
zzylol Sep 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions control_plane/src/clickhouse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ fn materialize_selected_sql(
let aggregation = BackendAggregation {
aggregation_id: String::new(),
metric_name: format!("{table}.{}", value.column().unwrap_or("constant")),
family: crate::physical::compiler::physical_materialization_family(family),
family: family.clone(),
window_secs,
spatial_filter: String::new(),
grouping: grouping.names(),
Expand Down Expand Up @@ -610,7 +610,7 @@ fn bind_selected_node(
..
} = clickhouse_materialization_leaf_contract(node, query.start_ms, query.end_ms)
.map_err(crate::query_plan::QueryPlanError::Invalid)?;
let expected = crate::physical::compiler::physical_materialization_family(family);
let expected = family.clone();
let selected = select_materialization(
&request.precompute_plan.materializations,
&table_ref,
Expand Down
2 changes: 1 addition & 1 deletion control_plane/src/emit/backend_wire.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
//! * the storage-routing table, which maps each metric's materialized summary
//! families to the query shapes the ASAP tier serves natively versus the
//! ones that belong to the archive;
//! * the aggregation and readout JSON the backend's `AggregationConfig`
//! * the aggregation and readout JSON the backend's `PrecomputeMaterialization`
//! parser consumes.
//!
//! `backend_plan::from_stage_config` reuses [`build_backend_aggregation_json`]
Expand Down
2 changes: 1 addition & 1 deletion control_plane/src/emit/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Backend-facing emission for a compiled physical plan.
//!
//! * [`backend_wire`] builds the storage-routing table and the aggregation /
//! readout JSON the backend's `AggregationConfig` parser consumes.
//! readout JSON the backend's `PrecomputeMaterialization` parser consumes.
//! * [`monitor`] carries the CDM monitor declarations.

pub mod backend_wire;
Expand Down
2 changes: 1 addition & 1 deletion control_plane/src/physical/backend_stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub struct BackendAggregation {
/// Internal-only id (see struct doc). Not on the wire.
pub aggregation_id: String,
/// Source metric the aggregation runs over. Required by the backend's
/// `AggregationConfig` parser.
/// `PrecomputeMaterialization` parser.
pub metric_name: String,
/// Planner-owned committed summary identity. Sketch entries carry a
/// validated `SketchKind` (category + algorithm + params); exact entries
Expand Down
68 changes: 22 additions & 46 deletions control_plane/src/physical/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1256,10 +1256,7 @@ impl DeploymentPlanCompiler {
.with_window_implementation_costs(window_costs);
let metric = selected.metric.clone();
let aggregation_id = format!("{}:{ordinal}:{}", query.query_id, metric);
// Rate is a readout over the same reset-aware counter state
// as Increase. Keep that semantic distinction in QueryPlan,
// while the physical store binds both to Increase state.
let physical_family = physical_materialization_family(&selected.family);
let physical_family = selected.family.clone();
let physical_algorithm = match &physical_family {
SummaryFamilyType::ExactAggregate(kind, _) => {
format!("{kind:?}").to_ascii_lowercase()
Expand Down Expand Up @@ -1698,7 +1695,7 @@ impl DeploymentPlanCompiler {
.map_err(|error| crate::query_plan::QueryPlanError::Invalid(error.to_string()))?
.family;
let window_ms = materialization.window_size.saturating_mul(1_000);
if materialization_family != physical_materialization_family(node_family)
if materialization_family != *node_family
|| window_ms == 0
|| source_window.unwrap_or(query.query_lookback_seconds).saturating_mul(1_000)
% window_ms != 0
Expand Down Expand Up @@ -2843,13 +2840,11 @@ pub(super) fn estimated_state_bytes(
A::HLL => 1u128 << parameter(&["precision", "p"], 14).min(24),
A::DDSketch => 64 * 1024,
A::Sum
| A::Count
| A::Increase
| A::Rate
| A::Min
| A::Max
| A::MultipleSum
| A::MultipleIncrease
| A::MultipleMin
| A::MultipleMax
| A::SingleSubpopulation
| A::MultipleSubpopulation => 256,
}
Expand All @@ -2867,7 +2862,7 @@ fn retained_partition_count(
if materialization.partitioning == Some(asap_types::sds::PopulationPartitioning::PerEntity)
|| matches!(
materialization.aggregation_type,
A::Increase | A::MultipleIncrease | A::Min | A::Max | A::MultipleMin | A::MultipleMax
A::Increase | A::Rate | A::Min | A::Max
)
|| !materialization.grouping_labels.names().is_empty()
{
Expand Down Expand Up @@ -3114,7 +3109,7 @@ pub(crate) fn raw_materialization_input_contract(
)
}

fn raw_time_series_input_contract(
pub fn raw_time_series_input_contract(
expr: &QueryExpr,
exact: bool,
) -> Result<(String, Option<u64>, String), String> {
Expand Down Expand Up @@ -3310,7 +3305,7 @@ fn physical_aggregation(
BackendAggregation {
aggregation_id,
metric_name: selected.metric.clone(),
family: physical_materialization_family(&selected.family),
family: selected.family.clone(),
window_secs: selected.window_secs.unwrap_or(query.query_lookback_seconds),
spatial_filter: selected.spatial_filter.clone(),
grouping: selected
Expand Down Expand Up @@ -3720,26 +3715,6 @@ fn collect_selected_materializations(
Ok(selected)
}

pub(crate) fn physical_materialization_family(family: &SummaryFamilyType) -> SummaryFamilyType {
match family {
SummaryFamilyType::ExactAggregate(planner_types::post_asap::ExactKind::Count, _) => {
// The SummaryStore Sum accumulator retains the observation count
// alongside its sum. Both logical states can share this producer.
SummaryFamilyType::ExactAggregate(
planner_types::post_asap::ExactKind::Sum,
planner_types::post_asap::ExactParams::Sum,
)
}
SummaryFamilyType::ExactAggregate(planner_types::post_asap::ExactKind::Rate, _) => {
SummaryFamilyType::ExactAggregate(
planner_types::post_asap::ExactKind::Increase,
planner_types::post_asap::ExactParams::Increase,
)
}
_ => family.clone(),
}
}

pub(super) fn sketch_params_json(params: &planner_types::post_asap::SketchParams) -> Value {
use planner_types::post_asap::SketchParams as P;
match params {
Expand Down Expand Up @@ -4529,8 +4504,7 @@ pub(crate) mod tests {
.find(|materialization| {
matches!(
materialization.aggregation_type,
asap_types::AggregationType::Increase
| asap_types::AggregationType::MultipleIncrease
asap_types::AggregationType::Rate
)
})
.expect("reset-aware exact counter");
Expand Down Expand Up @@ -5101,8 +5075,7 @@ pub(crate) mod tests {
.iter()
.all(|m| !matches!(
m.aggregation_type,
asap_types::AggregationType::Increase
| asap_types::AggregationType::MultipleIncrease
asap_types::AggregationType::Increase | asap_types::AggregationType::Rate
)));
let entry = plan.query_plan.entries.values().next().unwrap();
assert!(!entry.materialization_bindings().is_empty());
Expand Down Expand Up @@ -5660,7 +5633,7 @@ pub(crate) mod tests {
}

#[test]
fn rate_and_increase_share_physical_counter_state() {
fn rate_and_increase_keep_planner_families_distinct() {
let mut workload = request("rate", "rate(m[1m])");
workload
.queries
Expand All @@ -5669,10 +5642,14 @@ pub(crate) mod tests {
.compile_promql(workload, environment(10_000))
.unwrap();
assert_eq!(bundle.query_plan.entries.len(), 2);
assert_eq!(bundle.precompute_plan.materializations.len(), 1);
assert_eq!(bundle.precompute_plan.materializations.len(), 2);
for collector in &bundle.collector_plans {
assert_eq!(collector.materializations.len(), 1);
assert_eq!(collector.materializations[0].algorithm, "increase");
let algorithms: std::collections::BTreeSet<_> = collector
.materializations
.iter()
.map(|materialization| materialization.algorithm.as_str())
.collect();
assert_eq!(algorithms, ["increase", "rate"].into());
}
}

Expand All @@ -5692,8 +5669,7 @@ pub(crate) mod tests {
}

#[test]
fn exact_dashboard_binds_sum_and_count_to_one_local_producer() {
// Both dashboard roots use one packed raw accumulator, with explicit readouts.
fn exact_dashboard_preserves_distinct_sum_and_count_producers() {
let mut snapshot: BackendLocalPlanningInput = serde_json::from_str(include_str!(
"../../../docs/examples/asapquery-planning-snapshot.json"
))
Expand All @@ -5709,7 +5685,7 @@ pub(crate) mod tests {
entries.push(mean);
let (request, env) = snapshot.into_physical_compilation_request().unwrap();
let bundle = DeploymentPlanCompiler.compile_promql(request, env).unwrap();
assert_eq!(bundle.precompute_plan.materializations.len(), 1);
assert_eq!(bundle.precompute_plan.materializations.len(), 2);
assert_eq!(bundle.query_plan.entries.len(), 2);
for entry in bundle.query_plan.entries.values() {
assert!(
Expand All @@ -5719,7 +5695,7 @@ pub(crate) mod tests {
)),
"{entry:?}"
);
assert_eq!(entry.materialization_bindings().len(), 1);
assert!(!entry.materialization_bindings().is_empty());
}
assert!(bundle
.query_plan
Expand Down Expand Up @@ -7484,8 +7460,8 @@ pub(crate) mod tests {
assert_eq!(
materialization.accumulator_spec().unwrap().family,
SummaryFamilyType::ExactAggregate(
planner_types::post_asap::ExactKind::Increase,
planner_types::post_asap::ExactParams::Increase,
planner_types::post_asap::ExactKind::Rate,
planner_types::post_asap::ExactParams::Rate,
)
);
}
Expand Down
5 changes: 1 addition & 4 deletions control_plane/src/physical/pane_reuse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,7 @@ pub(super) fn share_additive_panes(
if !seen.insert(old)
|| m.derived_input.is_some()
|| derived_sources.contains(&old)
|| !matches!(
m.aggregation_type,
AggregationType::Sum | AggregationType::MultipleSum
)
|| !matches!(m.aggregation_type, AggregationType::Sum)
{
continue;
}
Expand Down
40 changes: 3 additions & 37 deletions control_plane/src/physical/post_asap/lower.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
//! Query binding delegates selection to Planner's costed workload search.
//! Backend-specific rate normalization remains part of the physical binding.

#![allow(dead_code)]

Expand Down Expand Up @@ -118,41 +117,8 @@ fn bind_recursive(
))
}

_ => {
let rewritten = rewrite_rate_to_increase(expr);
let node = crate::planner_selection::select_query(&rewritten, cost_model)?;
Ok(PostAsapPlan::Summary(node))
}
}
}

/// Rewrite Rate to Increase along the aggregate spine traversed by Planner.
/// This deployment computes rate by dividing the Increase readout by window
/// seconds, rather than storing a separate Rate accumulator.
fn rewrite_rate_to_increase(expr: &QueryExpr) -> QueryExpr {
match expr {
QueryExpr::Aggregate {
reduction,
measures: aggs,
output_names,
having,
child,
} => QueryExpr::Aggregate {
reduction: reduction.clone(),
measures: aggs
.iter()
.map(|intent| {
if matches!(intent, AggIntent::Rate) {
AggIntent::Increase
} else {
intent.clone()
}
})
.collect(),
output_names: output_names.clone(),
having: having.clone(),
child: Rc::new(rewrite_rate_to_increase(child)),
},
other => other.clone(),
_ => Ok(PostAsapPlan::Summary(
crate::planner_selection::select_query(expr, cost_model)?,
)),
}
}
32 changes: 10 additions & 22 deletions control_plane/src/physical/post_asap/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,13 +474,9 @@ fn phase_b_pattern_only_temporal_sum_binds_to_exact_agg() {
/// `ONLY_SPATIAL` — `sum by (host) (m)`.
/// Control plane path: `Aggregate{Sum, by=[host]}` over a bare `Scan`.
///
/// The old locally-defined `AggregationType::MultipleSum` (keyed vs
/// unkeyed sum) identity no longer exists at the L4 IR level —
/// `SummaryKind::Sum` covers both; the keyed/unkeyed distinction now
/// lives on `SummaryAgg::by` (non-empty ⇒ the old "MultipleSum" shape),
/// per `emit::mod.rs`'s exact-accumulator classification notes.
/// Family remains Sum; the reduction carries the grouping columns.
#[test]
fn phase_b_pattern_only_spatial_aggregate_binds_to_multiple_sum() {
fn phase_b_pattern_only_spatial_aggregate_binds_to_grouped_sum() {
let expr = QueryExpr::Aggregate {
reduction: Reduction::by(vec![1]), // service column
measures: vec![AggIntent::Sum { col: None }],
Expand All @@ -501,7 +497,7 @@ fn phase_b_pattern_only_spatial_aggregate_binds_to_multiple_sum() {
assert_eq!(
reduction.group_keys().map(|k| k.keys()),
Some(&[1][..]),
"keyed sum must carry the group-by column (the MultipleSum-equivalent signal)"
"Sum reduction must retain the group-by column"
);
}
other => panic!("expected SummaryAgg(Sum, by=[1]), got {other:?}"),
Expand All @@ -511,14 +507,9 @@ fn phase_b_pattern_only_spatial_aggregate_binds_to_multiple_sum() {
}

/// `ONE_TEMPORAL_ONE_SPATIAL` — `sum by (host) (rate(m[5m]))`.
/// `bind_query_expr` (not `implement_tree` directly) rewrites
/// `AggIntent::Rate` to `AggIntent::Increase` before binding (see
/// `lower.rs`'s `rewrite_rate_to_increase` — this deployment's data
/// plane has no Rate accumulator). The old
/// `AggregationType::MultipleIncrease` identity is now
/// `SummaryKind::Increase` with a non-empty `by`.
/// Planner preserves the Rate family and the `by` reduction independently.
#[test]
fn phase_b_pattern_temporal_and_spatial_combined_binds_to_multiple_increase() {
fn phase_b_pattern_temporal_and_spatial_combined_preserves_rate() {
let expr = QueryExpr::Aggregate {
reduction: Reduction::by(vec![1]),
measures: vec![AggIntent::Rate],
Expand All @@ -534,11 +525,11 @@ fn phase_b_pattern_temporal_and_spatial_combined_binds_to_multiple_increase() {
} => {
assert_eq!(
family,
&SummaryFamilyType::ExactAggregate(ExactKind::Increase, ExactParams::Increase)
&SummaryFamilyType::ExactAggregate(ExactKind::Rate, ExactParams::Rate)
);
assert_eq!(reduction.group_keys().map(|k| k.keys()), Some(&[1][..]));
}
other => panic!("expected SummaryAgg(Increase, by=[1]), got {other:?}"),
other => panic!("expected SummaryAgg(Rate, by=[1]), got {other:?}"),
},
other => panic!("expected Committed(Summary(_)), got {other:?}"),
}
Expand Down Expand Up @@ -671,12 +662,9 @@ fn phase_b_e2e_sum_by_preserves_grouping_label() {
);
}

/// `rate_increase.yaml` — the legacy planner emits a MultipleIncrease
/// (counter-reset adjusted) row. Control plane path: `Aggregate{Rate}` over
/// `Window` → `bind_query_expr` rewrites `Rate` to `Increase` and binds an
/// exact accumulator (`SummaryAgg{Increase}`) — no approximate summary
/// family. Both paths produce a single non-summary streaming row; the L5
/// emitter is the one that picks the actual MultipleIncrease processor.
/// A Rate query keeps Planner's exact Rate family through binding. The
/// physical emitter chooses the runtime processor without changing that
/// family identity.
#[test]
fn phase_b_e2e_rate_falls_through_to_logical() {
let bound = pipeline_l1_to_l4(
Expand Down
Loading