Conversation
…leaf nodes, precompute engine → upper AST) Implements SP-9 as described in docs/controller-optimization-problem.md. The SketchExpr tree produced by the query parser is now threaded through to the planner and split across pipeline stages instead of being discarded. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
zzylol
force-pushed
the
90-sp-9-ast-aware-hierarchical-stage-assignment-edge-collector-leaf-nodes-precompute-engine-upper-ast
branch
from
April 1, 2026 16:21
5ea277c to
21c6ffa
Compare
…to_promql - split_expr_by_stage now takes &QueryExpr instead of &SketchExpr. All SketchExpr-era node assignments are preserved; new QueryExpr-only nodes (HistogramQuantile, PromQLSubquery, BinaryOp, Aggregate, Sort+Limit, Join, SetOp) are assigned to the correct stage. - expr_to_promql replaced with a proper recursive descent over QueryExpr. Handles: histogram_quantile(φ, rate(…[w])), expr[range:step] subqueries, (lhs op rhs) vector binary ops with on(…)/ignoring(…)/group_left/group_right, Aggregate GROUP BY → by (keys), Sort+Limit → topk(n, …). - Label-filter extraction ported from Predicate list to ScalarExpr AND-tree: col="val", col!="val", col=~"re", col!~"re". - handle_plan unified to a single pipeline: parse_query_sketch → QueryExpr::from_sketch_expr → QueryOptimizer → split_expr_by_stage(&QueryExpr) → StagedPlan. SketchExpr path and analyze_with_sketch() removed from the hot path. - StageResourceBudgets duplicate definition resolved (kept SP-9 variant). - 12 new tests in stage_split covering all new node types, budget deferral, and expr_to_promql output. Total: 303 tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Merged algebra imports (QueryExpr + QueryOptimizer + SketchAllocator), combined query_parser imports (parse_query_sketch for stage-split path, parse_query_expr for plan_summary path), and kept wc_for_algebra from main. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Delete sketch_algebra.rs (721 lines) and sketch_rules.rs (683 lines) - Move shared types (SourceSpec, PartitionKeys, ColumnRef, SketchAggOp, ExactAgg, Predicate, FilterOp, FilterVal) into algebra/expr.rs - Parsers emit QueryExpr directly: parse_promql_expr / parse_sql_expr are now the only entry points; parse_query_sketch removed - query_parser/mod.rs: QeCollector walks QueryExpr for ParsedQuery - analyzer.rs: analyze_with_sketch() removed - main.rs: uses parse_query_expr() directly (no from_sketch_expr bridge) - All 264 tests pass; 39 SketchExpr-only tests removed with the IR Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
zzylol
deleted the
90-sp-9-ast-aware-hierarchical-stage-assignment-edge-collector-leaf-nodes-precompute-engine-upper-ast
branch
April 1, 2026 18:35
SieDeta
pushed a commit
that referenced
this pull request
Apr 17, 2026
… + recursive PromQL serialiser (#94) * feat: SP-9 AST-aware hierarchical stage assignment (edge collector → leaf nodes, precompute engine → upper AST) Implements SP-9 as described in docs/controller-optimization-problem.md. The SketchExpr tree produced by the query parser is now threaded through to the planner and split across pipeline stages instead of being discarded. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(SP-9): Option B — port stage_split to QueryExpr, recursive expr_to_promql - split_expr_by_stage now takes &QueryExpr instead of &SketchExpr. All SketchExpr-era node assignments are preserved; new QueryExpr-only nodes (HistogramQuantile, PromQLSubquery, BinaryOp, Aggregate, Sort+Limit, Join, SetOp) are assigned to the correct stage. - expr_to_promql replaced with a proper recursive descent over QueryExpr. Handles: histogram_quantile(φ, rate(…[w])), expr[range:step] subqueries, (lhs op rhs) vector binary ops with on(…)/ignoring(…)/group_left/group_right, Aggregate GROUP BY → by (keys), Sort+Limit → topk(n, …). - Label-filter extraction ported from Predicate list to ScalarExpr AND-tree: col="val", col!="val", col=~"re", col!~"re". - handle_plan unified to a single pipeline: parse_query_sketch → QueryExpr::from_sketch_expr → QueryOptimizer → split_expr_by_stage(&QueryExpr) → StagedPlan. SketchExpr path and analyze_with_sketch() removed from the hot path. - StageResourceBudgets duplicate definition resolved (kept SP-9 variant). - 12 new tests in stage_split covering all new node types, budget deferral, and expr_to_promql output. Total: 303 tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: delete SketchExpr — QueryExpr is the sole IR - Delete sketch_algebra.rs (721 lines) and sketch_rules.rs (683 lines) - Move shared types (SourceSpec, PartitionKeys, ColumnRef, SketchAggOp, ExactAgg, Predicate, FilterOp, FilterVal) into algebra/expr.rs - Parsers emit QueryExpr directly: parse_promql_expr / parse_sql_expr are now the only entry points; parse_query_sketch removed - query_parser/mod.rs: QeCollector walks QueryExpr for ParsedQuery - analyzer.rs: analyze_with_sketch() removed - main.rs: uses parse_query_expr() directly (no from_sketch_expr bridge) - All 264 tests pass; 39 SketchExpr-only tests removed with the IR Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2 tasks
zzylol
added a commit
that referenced
this pull request
May 7, 2026
…ath (#329) Phase 3.3 (#94) worked around the bootstrap-vs-replan-push divergence by adding a driver-side POST to /api/v1/plan after stack-up. This is the deep fix: handle_bootstrap_agent_config now mirrors handle_plan's typed L5 pipeline under USE_TYPED_STAGE_SPLIT=1 — bind_workload_typed → split_typed_three_stage → emit_for_runtime, dispatched by the X-Agent-Runtime header (defaults to Sketchcollector for legacy agents). Pinned-plan lookup via X-Agent-ID + the replanner's agent_to_metric mapping avoids drift between bootstrap and the first OpAMP push. A fresh agent fetching its initial config now sees the Phase 3.2.5 gorillas3 archive emit + warm-passthrough routing processor and the Phase ε.1.5 per-runtime dispatch without requiring the demo driver's explicit POST. The driver POSTs stay as a safety belt (they still exercise the typed-backend JSON push that the bootstrap GET doesn't fire). Backwards-compat: when USE_TYPED_STAGE_SPLIT is unset or the typed path can't resolve a workload (empty registry, unsupported topology) the handler falls back to the legacy generate_agent_config emit. Bootstrap never returns a 500 just because the typed path hit a gap. Tests: - bootstrap_legacy_path_when_env_unset — env unset → legacy ddsketch: - bootstrap_typed_path_when_env_set — env set + workload → typed ddsketchprocessor: - bootstrap_typed_path_sketchotap_runtime_dispatch — X-Agent-Runtime: sketchotap → otel_dataflow/v1 DAG YAML - bootstrap_typed_path_sketchtelegraf_runtime_dispatch → Telegraf TOML - bootstrap_typed_path_falls_back_to_legacy_when_no_workload — typed gate on but empty registry → legacy fallback (no 500) cargo test --release: 558 passed, 10 pre-existing failures unchanged. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
10 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #90.
What this PR actually does
SP-9 introduces per-stage sub-plans produced by walking the full query algebra AST, replacing the flat SP-3 assignment that put everything on the Agent stage.
New types in
types.rsStageResourceBudgets— per-stage memory/CPU caps (agent_memory_bytes,agent_cpu_micros_per_sample,backend_memory_bytes,precompute_memory_bytes)AgentSubPlan,BackendSubPlan,PrecomputeSubPlan,DbSubPlan— per-stage result structsStagedPlan— wraps the four sub-plans + adeferral_log: Vec<String>for observabilityCollectionPlan::staged_plan: Option<StagedPlan>—Somewhen aquery_stringwas supplied,Noneotherwise (SP-3 flat assignment remains the fallback)planner/stage_split.rs(new, ~980 lines)split_expr_by_stage(&QueryExpr, &StageResourceBudgets) → StagedPlanThe function takes a
QueryExpr(from the general algebra, PR #108) and performs a bottom-up walk, assigning each node to a stage:QueryExprnodeSource,Filter,Window, sketchAggPartition,Merge,Dedup,Agg { Exact(Sum|Count|Min|Max) }HistogramQuantile,PromQLSubquery,BinaryOp,Sort+Limit (TopK)Agg { Exact(Avg) }Budget deferral chain — when a sketch op's estimated memory exceeds the agent cap it is demoted to Backend; if it also exceeds the backend cap it moves to Precompute. Every demotion is logged in
StagedPlan::deferral_log.expr_to_promql(&QueryExpr) → String— recursive descent serialiser covering:histogram_quantile(φ, rate(…[w])),quantile_over_time(φ, …[w])expr[range:step]subquerieson(…)/ignoring(…)/group_left/group_rightAggregate GROUP BY→op by (keys) (…)Sort+Limit→topk(n, …)split_expr_by_stagetakes&QueryExpr, not&SketchExprThe initial commit used
SketchExprdirectly. A follow-up commit (Option B) ported everything toQueryExpr:parse_query_sketchstill returnsSketchExpr(parsers unchanged)handle_planconverts viaQueryExpr::from_sketch_expr()before callingsplit_expr_by_stageexpr_to_promqloperate purely onQueryExprconfig/backend.rsgenerate_backend_config_staged()added: emits adedupprocessor before the merge processor whenBackendSubPlan::has_dedupis true.config/precompute.rsbuild_precompute_jobs()usesstaged_plan.precompute.query_expr(the upper sub-tree serialised as PromQL) instead of the hardcodedquantile_over_time(0.99, …)template when the staged plan is present and active.main.rshandle_plannow runs:SP-3 flat assignment is unchanged and remains the fallback when
query_stringis absent.Test coverage — 16 new tests in
planner/stage_split.rs(303 total)ddsketch_agg_goes_to_agenthll_stays_at_agent_by_defaultaggregate_sum_goes_to_backendaggregate_without_group_by_avg_goes_to_dbpartition_group_by_goes_to_backendtopk_goes_to_precomputehistogram_quantile_activates_precomputebinary_op_activates_precomputeddsketch_deferred_to_backend_when_agent_budget_exceededddsketch_deferred_to_precompute_when_both_budgets_exceededlabel_matchers_and_treeAgentSubPlan::label_filterspromql_ddsketch_with_filter_and_windowexpr_to_promqlfor DDSketch + Windowpromql_histogram_quantileexpr_to_promqlfor histogram_quantilepromql_subquery_renders_rangeexpr_to_promqlfor subquery[range:step]promql_binary_op_renders_operatorexpr_to_promqlfor vector binary opspromql_topk_wraps_innerexpr_to_promqlfor Sort+Limit → topkBackward compatibility
Analyzer::analyze()is unchanged; all existing callers compile without modification.CollectionPlan::staged_plandefaults toNone— no change to existing plan constructors.query_stringis absent.🤖 Generated with Claude Code