Repository navigation
Description
Concrete maintenance problem
The Rust workspace has about 180k lines: roughly 97k production and 83k test. A repo-wide over-engineering audit found a lot of dead code, abstractions with only one implementation, and two planning pipelines running side by side. Together these make the code hard to follow.
The compiler couldn't flag any of this, because data_plane/src/lib.rs:1 and 14 control-plane modules turn off its dead-code warnings with #![allow(dead_code, unused_imports, …)].
Method: reference counts across the repo, done once with test code included and once with it stripped, plus cargo rustc -- --force-warn dead_code --force-warn unused_imports on both library crates. Grep-based counts can miss uses through macros or common method names, so every deletion needs cargo check and the test suite before it merges.
Before and after structure
Findings are ranked by the largest cut first. Line counts are estimates and include tests that exist only to cover the deleted code.
-
Disconnected sketch cost-summary planner (≈ −2,750 lines). The files are
control_plane/src/physical/{allocator,plan,planner,window_fusion,deployment}.rs. Their only production output is theplan_summaryfield in the/api/v1/planresponse. The handler derives deployment configs separately: the old allocator’s placement decisions do not determine the emitted configs. No in-repo consumer of this response field was found. Remove this disconnected chain and the field, subject to checking external API compatibility.V2 follow-up, separate from this cleanup: track resource-budget-aware placement (memory, CPU, and bandwidth) and, if needed, cost explanations derived from the actual emitted deployment plan. The current physical compiler’s deployment inputs do not expose per-stage resource budgets; deleting this chain does not establish v2 feature parity for that capability. Reuse existing planner/cost-model sketch selection and parameter sizing, and preserve the physical compiler’s window-lifecycle invariants and tests. Do not port the old allocator wholesale: its estimates include fixed compression factors, and its precompute fallback does not check that stage’s remaining budget.
-
Test-only PromQL planning inside the data plane (≈ −1,200 lines). This covers
asap_query_engine/post_asap_planner.rs, the*_from_summary_executorfunctions inlive_serve.rs, andexecute_post_asap_*inpost_asap_readout.rs. Production never reaches this code:engine.rs:703andengine.rs:1057branch on#[cfg(test)]/#[cfg(not(test))], so tests run a different query path than production. After: tests install a QueryPlan the way production does, and thecfg(test)branches go away. -
Comments that narrate history (≈ −1,100 lines). About 1,050 comment lines tell project history ("Phase γ", "B7.5 retired", "M2.3.6g", "used to…").
control_plane/src/lib.rs:26also has a 90-line old→new module-mapping table that points at modules that no longer exist (intent_algebra,optimizer). Keep only comments that explain current intent or invariants, since git history already records the rest. -
Public items that are dead or used only by tests (≈ −900 lines, about 110 items). The biggest groups:
SketchStore::{descriptor_counts, policy_count, item_label_for, …}hot_reload_config::{discard_staged, retire_drained, materialization_statuses}planner_selection::{select_workload, select_summary_or_keep}query_plan::compile_bound*servers/metrics.rsstart_ingest_timerandrecord_ingest_*- the public
spawn_mock_thanos_*helpers inthanos_query_engine/forward.rs
Delete these or move them under
#[cfg(test)]. -
Modules only their own tests use (−388 lines).
control_plane/src/physical/summary_reconcile.rsandcontrol_plane/src/threshold_alloc.rs. -
Factory traits nobody uses (≈ −150 lines).
SingleSubpopulationAggregateFactory,MultipleSubpopulationAggregateFactory,AccumulatorFactory(which has no implementations), and the 4*AccumulatorFactorystructs instorage_engines/types/traits.rs:225-280and the operator files. None of them is ever constructed. -
WindowMerger/NaiveMerger/create_window_merger(≈ −70 lines). This is a trait plus a factory with one implementation, kept for merge strategies planned for "later" (sketch_db/query/window_merger.rs:19). Replace it with amerge_all(&[Box<dyn AggregateCore>])function. -
Query adapter traits (≈ −80 lines). There are 3 traits (
QueryRequestAdapter,QueryResponseAdapter,HttpProtocolAdapter) for 2 near-identical Prometheus-style adapters, andcreate_http_adapter(adapters/factory.rs:8) is amatchwith one arm. Collapse them into one trait and construct adapters directly. -
AsyncQueryNodeRuntime/execute_async(≈ −90 lines).physical_dag.rs:28. The only implementation is a test counter. -
Other traits with one implementation (≈ −100 lines). Replace each with inherent methods or free functions:
RealizationProvider→ExistingRealizations(physical/realization.rs:13)Emitter→ThreeStageEmitter(colored_dag/emitter.rs:173)- the copied-in
SummaryExecutor, which has one production implementation plus 2 test mocks
-
Files that only re-export something (≈ −70 lines). Import from where each item is actually defined:
query_engines/canonical/mod.rs(0 users)physical/topology.rs(0 users)physical/summary_catalog.rsstorage_engines/types/storage_backend.rs- the old
timeline_dispatch/window_mergeraliases inquery_engines/mod.rs:29(0 users) - the
asap_tieralias StoreResult
-
Kill switches whose "off" setting just disables the feature (≈ −60 lines).
USE_TYPED_STAGE_SPLIT(physical/stage_split.rs:27, pluselsebranches inmain.rsandreplan.rs) andASAP_SUMMARY_EXECUTOR_LIVE(live_serve.rs:78, checked in 5 serving functions). Turning the second one off breaks all planned serving. -
Router written out 3 times (≈ −60 lines). The production router is at
control_plane/src/main.rs:514, with hand-copied test versions at:2268and:3303. Build it in onefn app(state) -> Routerand use that everywhere. -
MergeableAccumulator<T>(≈ −40 lines).Tis alwaysSelf, and the call sites look like<X as MergeableAccumulator<X>>::merge_accumulators(...). Replace it with an inherentX::merge(vec). -
types_v2.rs(≈ −30 lines). Merge it intotypes.rs, drop itsallow(dead_code), and delete the unusedBindingNameand helper functions. -
Private dead code found once warnings were forced on (≈ −60 lines).
ThroughputTotals,since,throughput_totals(precompute_engine/metrics.rs)MaintenanceRuntime::summaryASAPQueryEngine.prometheus_scrape_intervalflusher::metadata_storecolored_dag::allocator::binding_stage- unused imports in
emitter.rs:39
After cleanup, remove the blanket
#![allow(dead_code, …)]attributes so the compiler keeps catching this. -
Unused dependencies.
rusqlite(which compiles SQLite from source),uuid,structoptandurlencodingindata_plane/Cargo.toml, andzstdandtokio-streamincontrol_plane/Cargo.toml. Separately,reqwest0.11 and 0.12 are both built.
Net: about −7,000 lines and −6 dependencies, not counting item 18.
- Two planning pipelines (decision needed, probably −6k lines or more). The README itself calls
POST /api/v1/planthe "legacy planning API", but it's still fully alive. It runs throughpipeline.rs,replan.rs,physical/workload_planner.rs,physical/plan_cache.rs,physical/deployment_cost/{pareto,tco,online,delta}.rs, and the/plan/auto,/pareto,/tco,/rollback,/diff,/agentsand/confighandlers. Thephysical-plan/compile-and-publishcompiler is the path that e2e tests and user docs use. In this repo, nothing exercises/plan/auto,/pareto,/tco,/agentsor/config. The complication is that the startupworkloads.yamlregistry still goes through the legacy path. Consolidating onto the physical compiler would remove the largest source of duplicate concepts, but it changes the API, so it needs a separate decision.
Behavior that must remain unchanged
Items 1–17 should cause no behavior change except that the plan_summary response field disappears (item 1, subject to external API compatibility review). Removing the disconnected summary planner must not change emitted deployment configs and does not add resource-budget enforcement to v2. These must keep working:
- the physical-plan compile, publish and install flow
- PromQL/SQL serving from installed QueryPlans
- ingest and precompute
- the HTTP routes used by docs and e2e tests
Item 18 removes API surface on purpose and is out of scope until it's decided.
Why the proposed structure is minimally complex
Every item deletes code or collapses a layer. None adds a new abstraction.
Existing unit and end-to-end protection
scripts/e2e.shand the process e2e tests indata_plane/testsandcontrol_plane/testscover the physical-plan path.- Item 2 changes tests that currently depend on the
cfg(test)-only branch (for example, theASAP_SUMMARY_EXECUTOR_LIVEtests indata_plane/tests/e2e_controller_plans_and_backend_serves.rs). Those tests have to switch to an installed QueryPlan first.
Compatibility or migration impact
- Item 1 drops
plan_summaryfrom the/api/v1/planresponse. No in-repo reader was found, but this does not establish that external clients do not use it; check external usage before removal and deprecate the field first if compatibility requires it. Resource-budget-aware placement and deployment-derived cost explanations are separate v2 follow-ups. - Items 4, 6 and 11 remove public Rust items. The only consumers are inside this workspace.
- Item 18 would remove HTTP endpoints and move the
workloads.yamlregistry onto the physical compiler.
Suggested order: split the work into small PRs, starting with the least ambiguous items (17, 16, 5, 1, 2).
Activity
milindsrivastava1997 commentedon Sep 13, 2026
FYI @zzylol
milindsrivastava1997 commentedon Sep 13, 2026
Addendum to item 2: the rest of that block in
ASAPQueryEngine::execute_atis also dead in productionItem 2 cites the
#[cfg(test)] None => serve_instant_from_summary_executor(...)arm atengine.rs:1057. The block around that arm (engine.rs:1040-1135at674b9573) is unreachable in non-test builds too, apart from a plan-swap race:lookupsucceeds. The firstif let(L1014-L1034) always returns, eitherOkor through?fromprepare_logical/execute_logical_entry.lookupfails. The second block runs the samequery_plan.lookup(query)on a fresh snapshot, gets the sameQueryNotPlanned, and maps it toCapabilityMiss.So these parts never run for instant queries in production:
Some(plan) => Ok(entry) => serve_instant_from_query_planarmmark_materializing/mark_ready/mark_servingreadiness handlingThe only way in is
ArcSwapinstalling a plan between the twophysical_plan_snapshot()calls.Suggestion: after item 2 removes the
cfg(test)arm, delete the whole block. Whenlookupfails, returnCapabilityMiss(with the capability-miss notify) straight away.Not dead:
stitch_warm_and_archive/archive_engineare still used byexecute_range_promql_modern(L793-L800). That path is reachable for planned range queries with noLogicalnodes, because only entries that containLogicalnodes return early throughexecute_logical_range.sketch_indexisNone.🤖 Generated with Claude Code
Remove unused interfaces and historical commentary (#703) (#711)
zzylol commentedon Sep 13, 2026
Item 18: consolidating onto the ASAPPlanner path
Four stacked PRs: #713 → #715 → #718 → #719. Together about −25,900 lines;
control_planegoes from ~51k to 29,070,main.rsfrom 3,500+ to 1,108.Three things in the item-18 write-up turned out not to hold on
main, and each one made the work smaller.1. The two pipelines already converge on the backend side
PhysicalCompilerdoes not build its own backend plan. It assembles aBackendStageConfigand callsbackend_plan::from_stage_config, which reusesemit::stage_config::build_backend_aggregation_json— the same builder the legacy JSON push used. That module's doc calls fingerprint parity the load-bearing invariant, and it is:BackendPlanmaterializations and the JSON wire format share onePolicyFingerprintidentity space.So the duplication was never "two pipelines". It was the front half (query → summary decision) plus the publication contract, with a shared back half.
2.
POST /api/v1/planhad no working consumerThe item lists it as "still fully alive". It is routed, but both apparent consumers are broken or unwired:
The capability-miss feedback loop never worked. The data plane POSTs a
CapabilityMissPayload—{kind, metric, statistics, data_range_ms, grouping_labels, spatial_filter_normalized}.handle_planaccepts aQuerySpec, whoseaccuracy_slahas no serde default. Deserializing that exact payload againstQuerySpecgives:No control-plane handler accepts that payload at all — no
capability_missroute, and no field namedspatial_filter_normalizedanywhere in the crate. The non-2xx becomes anErrthatspawn_capability_miss_notifylogs at WARN and drops. Silent no-op in production.config_fetcher::ControlPlaneClient— which pollsGET /plan/:metricand posts/plan— is never constructed outside its own module.That left
control_plane/tests/component_process_e2e.rsas the only real caller, and it exercises the legacy path itself.Consequence: the three gaps that would have made porting
handle_planontoPhysicalCompilerawkward never had to be closed —QuerySpec::query_stringbeingOption, the absentLifecyclePlanningInputcost evidence, and the absentwindow_implementations(select_lifecyclehard-errors without a concrete implementation). Item 18 is a deletion, not a rewrite.3.
collector_idsis already optional, and CDM monitors are deadPhysicalDeploymentTarget::BackendLocalRemoteWriterequirescollector_idsempty;DistributedCollectorsrequires it non-empty. Already onmain.MonitorIntentthreads throughpost_typed_backend_for_role→push_documents_coupled→push_cumulative_entriesand is dropped there as_monitors. It is dead on both paths, so it retires with the legacy code rather than being ported.One real gap, fixed first (#713)
storage_routing. The physical publication passedNone, so a deployment planned throughcompile-and-publishinstalled no routing table and archive-shape queries missed.build_routing_entryonly ever needed the per-metric sketch algorithms, so it now takes those directly and both paths run one classifier over the same decisions.What the deletions covered
/plan/auto,/plan/pareto,/plan/:metric/rollback,/plan/:metric/diff,/agents,/config/:metric) and the autonomous allocation chain behind/plan/auto.epsilon_allocsurvives:derive_sample_pandsplit_budgetare live on the physical path./plan,/plan/:metric, and the dead capability-miss loop.workloads.yamlpre-population →Analyzer/DeploymentPlanCompiler→PlanStore/WorkloadStore→Replanner→Scraper→ OpAMP hooks →colored_dag→ per-runtime emitters.Two pieces extracted rather than deleted, because the ASAPPlanner path needs them:
physical::backend_stage(the four backend types) andemit::backend_wire(the routing classifier plusbuild_backend_aggregation_json, still the single source of the aggregation wire shape).Items closed along the way
Item 10's
RealizationProvider::stages(no callers), item 11'sphysical/topology.rs(pure re-export), item 12'sUSE_TYPED_STAGE_SPLIT(its "off" branch was the legacy emitter).Behaviour changes
/metricsno longer exposesasap_active_plan_id; the gauge readPlanStore.GET /api/v1/collector-config/agentis gone. The OpAMPCollectorPlanchannel stays, and ASAPCollector'sasapedgeprocessoralready implementsReceiveCollectorPlan, but any deployment pointing a collector at--config=http://control_plane:8080/api/v1/collector-config/agenthas to move to that channel.Still open
data_plane/tests/e2e_controller_plans_and_backend_serves.rsbuilds its config throughbind_workload_typed→split_typed_three_stage→emit_backend_streaming_config_json, all of which #719 removes. This is the test item 2 already flags as needing to install a QueryPlan the way production does. Its install half is already modern —post_full_configparses the legacy JSON into aStreamingConfigand projects it into a physical-plan artifact — so the rewrite replaces the scaffolding, not the 2,456 lines of OTLP → precompute → PromQL coverage. Tracked as part of #719.Note for CI
rustc 1.98.0ICEs onevaluate_obligationunder incremental compilation while checking these changes.CARGO_INCREMENTAL=0works around it.