You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Explore if we should move the Controller to Rust #101
There is shared query parsing and matching logic between the QueryEngine and the Controller. This logic will keep on expanding and it is best to keep this in the same language
At some point, the Controller might become an online module that observes incoming queries and data to tweak query plans, and this might need to be higher performance.
use indexmap::IndexMap;use serde::{Deserialize,Serialize};#[derive(Debug,Clone,Deserialize,Serialize)]pubstructControllerConfig{pubquery_groups:Vec<QueryGroup>,pubmetrics:Vec<MetricDefinition>,#[serde(default)]pubsketch_parameters:Option<SketchParameterOverrides>,#[serde(default)]pubaggregate_cleanup:Option<AggregateCleanupConfig>,}#[derive(Debug,Clone,Deserialize,Serialize)]pubstructQueryGroup{pubid:u32,pubqueries:Vec<String>,pubrepetition_delay:u64,// seconds#[serde(default)]pubclient_options:Option<ClientOptions>,#[serde(default)]pubcontroller_options:Option<ControllerOptions>,}#[derive(Debug,Clone,Deserialize,Serialize)]pubstructControllerOptions{pubaccuracy_sla:f64,publatency_sla:f64,}#[derive(Debug,Clone,Deserialize,Serialize)]pubstructMetricDefinition{pubmetric:String,publabels:Vec<String>,#[serde(default)]pubcardinality:Option<IndexMap<String,u64>>,}// ... additional structs
Streaming Config Output (config/streaming.rs)
use indexmap::IndexMap;use serde::{Deserialize,Serialize};#[derive(Debug,Clone,Serialize,Deserialize)]#[serde(rename_all = "camelCase")]pubstructStreamingConfig{pubaggregations:Vec<AggregationConfig>,pubmetrics:IndexMap<String,Vec<String>>,}#[derive(Debug,Clone,Serialize,Deserialize)]#[serde(rename_all = "camelCase")]pubstructAggregationConfig{pubaggregation_id:u32,pubaggregation_type:AggregationType,pubaggregation_sub_type:String,pubmetric:String,pubspatial_filter:String,pubwindow_type:WindowType,pubwindow_size:u64,pubslide_interval:u64,pubtumbling_window_size:u64,pubparameters:IndexMap<String, serde_json::Value>,publabels:LabelConfig,}#[derive(Debug,Clone,Serialize,Deserialize)]pubstructLabelConfig{pubrollup:Vec<String>,pubgrouping:Vec<String>,pubaggregated:Vec<String>,}#[derive(Debug,Clone,Copy,Serialize,Deserialize)]pubenumAggregationType{DeltaSetAggregator,CountMinSketch,CountMinSketchWithHeap,DatasketchesKLL,HydraKLL,MultipleIncrease,Sum,Count,MinMax,}#[derive(Debug,Clone,Copy,Serialize,Deserialize)]#[serde(rename_all = "lowercase")]pubenumWindowType{Tumbling,Sliding,}
Inference Config Output (config/inference.rs)
use indexmap::IndexMap;use serde::{Deserialize,Serialize};#[derive(Debug,Clone,Serialize,Deserialize)]pubstructInferenceConfig{pubqueries:Vec<QueryConfig>,pubmetrics:IndexMap<String,Vec<String>>,}#[derive(Debug,Clone,Serialize,Deserialize)]pubstructQueryConfig{pubquery:String,pubaggregations:Vec<QueryAggregationRef>,}#[derive(Debug,Clone,Serialize,Deserialize)]pubstructQueryAggregationRef{pubaggregation_id:u32,pubnum_aggregates_to_retain:Option<u64>,}
Phase 3: Library API Design
Public API (lib.rs)
pubmod config;pubmod error;use config::{ControllerConfig,StreamingConfig,InferenceConfig};use error::ControllerError;/// Main controller that generates streaming and inference configspubstructController{config:ControllerConfig,options:ControllerOptions,}#[derive(Debug,Clone,Default)]pubstructControllerOptions{/// Prometheus scrape interval in secondspubprometheus_scrape_interval:u64,/// Target streaming enginepubstreaming_engine:StreamingEngine,/// Enable punting (reject queries that won't perform well)pubenable_punting:bool,}#[derive(Debug,Clone,Copy,Default)]pubenumStreamingEngine{#[default]Arroyo,Flink,}implController{/// Create controller from parsed configpubfnnew(config:ControllerConfig,options:ControllerOptions) -> Self;/// Create controller from YAML file pathpubfnfrom_file(path:&Path,options:ControllerOptions) -> Result<Self,ControllerError>;/// Create controller from YAML stringpubfnfrom_yaml(yaml:&str,options:ControllerOptions) -> Result<Self,ControllerError>;/// Generate both configspubfngenerate(&self) -> Result<ControllerOutput,ControllerError>;/// Generate and write to directorypubfngenerate_to_dir(&self,output_dir:&Path) -> Result<ControllerOutput,ControllerError>;}#[derive(Debug,Clone)]pubstructControllerOutput{pubstreaming_config:StreamingConfig,pubinference_config:InferenceConfig,/// Queries that were punted (if punting enabled)pubpunted_queries:Vec<PuntedQuery>,}#[derive(Debug,Clone)]pubstructPuntedQuery{pubquery:String,pubreason:String,}
Usage from QueryEngineRust
use controller_rust::{Controller,ControllerOptions,StreamingEngine};// Option 1: From filelet controller = Controller::from_file(Path::new("controller-config.yaml"),ControllerOptions{prometheus_scrape_interval:15,streaming_engine:StreamingEngine::Arroyo,enable_punting:true,},)?;let output = controller.generate()?;// Option 2: From parsed config (if QueryEngine already has it)let controller = Controller::new(config, options);let output = controller.generate()?;// Access the configslet streaming = output.streaming_config;let inference = output.inference_config;
Phase 4: CLI Design
Command Line Interface
controller-rust 0.1.0
ASAP Controller - generates streaming and inference configs from query workloads
USAGE:
controller [OPTIONS] --input <FILE>
OPTIONS:
-i, --input <FILE> Input controller config YAML file
-o, --output-dir <DIR> Output directory [default: .]
-s, --scrape-interval <SECS> Prometheus scrape interval [default: 15]
-e, --engine <ENGINE> Streaming engine: arroyo|flink [default: arroyo]
--enable-punting Enable query punting for performance
--streaming-only Only output streaming_config.yaml
--inference-only Only output inference_config.yaml
--json Output as JSON instead of YAML
-v, --verbose Enable verbose logging
-h, --help Print help
-V, --version Print version
Activity
milindsrivastava1997 commentedon Mar 4, 2026
PRO-355
milindsrivastava1997 commentedon Mar 4, 2026
Controller Rust Port Plan
Overview
Port the Python Controller to Rust, providing both a standalone CLI binary and a library for use by QueryEngineRust and other Rust services.
Current State: Python Controller (~1,264 LOC) in
Controller/Target: Rust crate
controller_rustinControllerRust/Goals
Phase 0: Cargo Workspace Setup
Create a workspace at the repo root to manage related Rust crates together.
Files to Create/Modify
Create
asap-internal/Cargo.toml(workspace root):Update existing
Cargo.tomlfiles to use workspace dependencies:QueryEngineRust/Cargo.tomlCommonDependencies/dependencies/rs/promql_utilities/Cargo.tomlCommonDependencies/dependencies/rs/sql_utilities/Cargo.tomlUpdate
Utilities/components.conf:Phase 1: Crate Structure
Directory Layout
Cargo.toml
Phase 2: Config Types (with Serde Validation)
Input Config (
config/input.rs)Streaming Config Output (
config/streaming.rs)Inference Config Output (
config/inference.rs)Phase 3: Library API Design
Public API (
lib.rs)Usage from QueryEngineRust
Phase 4: CLI Design
Command Line Interface
Implementation (
main.rs)Phase 5: Testing Infrastructure
Test Strategy
Use the same pattern as
CommonDependencies/tests/compare_matched_tokens/:Directory Structure
Test Case Format (
test_cases.json){ "test_cases": [ { "id": "final_generated_workload_1", "description": "Mixed spatial and temporal queries", "input_config": "configs/case_001.yaml", "prometheus_scrape_interval": 15, "streaming_engine": "arroyo", "enable_punting": false }, { "id": "quantile_queries", "description": "Quantile-heavy workload", "input_config": "configs/case_002.yaml", "prometheus_scrape_interval": 1, "streaming_engine": "arroyo", "enable_punting": true } ] }Semantic Comparison (
comparator.py)Test Corpus Selection
Extract test configs from
experiment_outputs/:final_generated_workload_prometheus_*qot_*quantile_1s_*non_quantile_*diverse_test_*Script to extract configs:
Phase 6: Implementation Order
Step 1: Workspace Setup
asap-internal/Cargo.tomlworkspace fileQueryEngineRust/Cargo.tomlto use workspace depspromql_utilities/Cargo.tomlto use workspace depssql_utilities/Cargo.tomlto use workspace depscargo buildworks from repo rootStep 2: Scaffold ControllerRust
ControllerRust/directory structureCargo.tomlwith workspace depsconfig/module)error.rs)lib.rsandmain.rsStep 3: Core Logic
query/patterns.rs)query/classification.rs)query/single_query.rs)sketch/parameters.rs)sketch/window.rs)Step 4: Config Generation
Controller::generate()orchestrationStep 5: CLI
Step 6: Testing Infrastructure
test_cases.jsonpython_runner.pycomparator.pymaster_test_runner.pyStep 7: Integration
controller_rustdependency toQueryEngineRust/Cargo.tomlUtilities/components.confDependencies Summary
From Workspace
promql_utilities- PromQL parsing, pattern matching, query classificationserde,serde_yaml,serde_json- Serializationthiserror,anyhow- Error handlingtracing,tracing-subscriber- Loggingclap- CLI parsingchrono- Time handlingindexmap- Ordered maps for deterministic YAML outputNew Dependencies
promql-parser = "0.5.0"- Already used by promql_utilitiesRisks and Mitigations
indexmapfor key ordering; comparison tests ignore cosmetic differencesEstimated LOC
config/(all structs)query/(patterns, classification)sketch/(parameters, windows)engine/(arroyo, flink)lib.rs+error.rsmain.rs(CLI)Plus ~300-400 LOC for test infrastructure (Python comparator, test runner).
Success Criteria
cargo buildsucceeds for workspacecargo testpasses all unit testscontroller_rustas a library