Skip to content

Commit 6848119

Browse files
docs(planner): document windowing override
1 parent 23547e0 commit 6848119

12 files changed

Lines changed: 105 additions & 3 deletions

File tree

‎asap-planner-rs/src/lib.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub use asap_types::PromQLSchema;
1515
pub use config::input::ControllerConfig;
1616
pub use config::input::ElasticDSLControllerConfig;
1717
pub use config::input::SQLControllerConfig;
18+
pub use config::input::{WindowingConfig, WindowingType};
1819
pub use elastic_dsl::ElasticController;
1920
pub use elastic_dsl::ElasticIndexSchemaBuilder;
2021
pub use elastic_dsl::ElasticRuntimeOptions;

‎asap-planner-rs/src/planner/window.rs‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,14 @@ pub fn apply_windowing_override(
105105
config.slide_interval_ms = config.window_size_ms;
106106
}
107107
WindowingType::Sliding => {
108-
let divisor = windowing.slide_divisor.expect("validated sliding divisor");
108+
let divisor = match windowing.slide_divisor {
109+
Some(divisor) => divisor,
110+
None => {
111+
return Err(
112+
"windowing.slide_divisor is required for sliding windows".to_string()
113+
)
114+
}
115+
};
109116
if !config.window_size_ms.is_multiple_of(divisor) {
110117
return Err(format!(
111118
"window_size_ms ({}) must be evenly divisible by slide_divisor ({divisor})",

‎asap-planner-rs/src/promql/generator.rs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ pub fn generate_plan(
3131
) -> Result<GeneratorOutput, ControllerError> {
3232
let metric_schema = schema.clone();
3333

34+
if let Some(windowing) = &controller_config.windowing {
35+
windowing
36+
.validate()
37+
.map_err(ControllerError::PlannerError)?;
38+
}
39+
3440
// Determine cleanup policy
3541
let cleanup_policy = controller_config
3642
.aggregate_cleanup

‎asap-planner-rs/src/sql/generator.rs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ pub fn generate_sql_plan(
2525
config: &SQLControllerConfig,
2626
opts: &SQLRuntimeOptions,
2727
) -> Result<GeneratorOutput, ControllerError> {
28+
if let Some(windowing) = &config.windowing {
29+
windowing
30+
.validate()
31+
.map_err(ControllerError::PlannerError)?;
32+
}
33+
2834
let eval_time: f64 = opts.query_evaluation_time.unwrap_or_else(|| {
2935
SystemTime::now()
3036
.duration_since(UNIX_EPOCH)

‎asap-planner-rs/tests/integration.rs‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,39 @@ query_groups: []
172172
.contains("windowing.slide_divisor is only valid for sliding windows"));
173173
}
174174

175+
#[test]
176+
fn explicit_tumbling_window_override_keeps_tumbling_candidates() {
177+
let controller = Controller::from_yaml_with_schema(
178+
r#"
179+
windowing:
180+
type: "tumbling"
181+
query_groups:
182+
- id: 1
183+
queries:
184+
- "rate(http_requests_total[1m])"
185+
repetition_delay_ms: 60000
186+
controller_options:
187+
accuracy_sla: 0.99
188+
latency_sla: 1.0
189+
"#,
190+
http_requests_schema(),
191+
arroyo_opts(),
192+
)
193+
.unwrap();
194+
195+
let output = controller.generate().unwrap();
196+
let streaming: serde_yaml::Value =
197+
serde_yaml::from_str(&output.to_streaming_yaml_string().unwrap()).unwrap();
198+
let aggregation = &streaming["aggregations"][0];
199+
200+
assert_eq!(aggregation["windowType"].as_str(), Some("tumbling"));
201+
assert_eq!(
202+
aggregation["slideIntervalMs"].as_u64(),
203+
aggregation["windowSizeMs"].as_u64()
204+
);
205+
assert_ne!(aggregation["windowType"].as_str(), Some("sliding"));
206+
}
207+
175208
/// Schema for binary arithmetic tests: errors_total and requests_total.
176209
fn binary_arithmetic_schema() -> PromQLSchema {
177210
PromQLSchema::new()

‎asap-tools/experiments/CONFIG_PARAMETERS_REFERENCE.md‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,25 @@ These parameters must be provided for all experiment scripts:
204204
- **Example**: `"10s"`
205205
- **Usage**: Controls pre-computed metric updates
206206

207+
## Planner Windowing Override
208+
209+
#### `windowing` (object, optional)
210+
- **Description**: Global manual override for the planner's window type
211+
- **Default**: Omitted, which preserves tumbling-window planning
212+
- **Choices**: `tumbling`, `sliding`
213+
- **Scope**: Applies to PromQL and SQL planner inputs; ElasticDSL is unchanged
214+
215+
#### `windowing.type` (string, required when `windowing` is present)
216+
- **Description**: Selects the planner window type
217+
- **Choices**: `tumbling`, `sliding`
218+
219+
#### `windowing.slide_divisor` (int, required for sliding)
220+
- **Description**: Computes each query's slide interval as
221+
`window_size_ms / slide_divisor`
222+
- **Validation**: Must be at least 2 and must evenly divide every supported
223+
query's computed window size; invalid workloads fail plan generation
224+
- **Constraint**: Do not provide this field for `tumbling`
225+
207226
---
208227

209228
## Monitoring Configuration

‎asap-tools/experiments/config/config.yaml‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ query_engine:
9999
controller:
100100
punting: true # Enable query punting based on performance heuristics (should_be_performant check)
101101

102+
# Optional manual planner windowing override. Omit this block to preserve the
103+
# default tumbling-window behavior. For sliding windows, the divisor must be
104+
# at least 2 and must evenly divide every query's computed window size.
105+
# windowing:
106+
# type: "sliding"
107+
# slide_divisor: 4
108+
102109
# Aggregate cleanup configuration
103110
# Policy options:
104111
# - "circular_buffer": Keep N most recent aggregates (fixed-count cleanup)

‎asap-tools/experiments/experiment_only_ingest_path.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ def main(cfg: DictConfig):
190190
local_experiment_root_dir,
191191
cfg.aggregate_cleanup,
192192
cfg.get("sketch_parameters", None),
193+
cfg.get("windowing", None),
193194
)
194195
)
195196
sync.rsync_controller_client_configs(

‎asap-tools/experiments/experiment_run_clickhouse.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,10 @@ def main(cfg: DictConfig) -> None:
377377

378378
# Generate and rsync the planner input config to the node
379379
planner_input_yaml = config.generate_sql_planner_input(
380-
ep.query_groups, dataset_cfg, cfg.get("sketch_parameters", None)
380+
ep.query_groups,
381+
dataset_cfg,
382+
cfg.get("sketch_parameters", None),
383+
cfg.get("windowing", None),
381384
)
382385
local_planner_input = os.path.join(
383386
local_controller_dir, "planner_input.yaml"

‎asap-tools/experiments/experiment_run_e2e.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ def main(cfg: DictConfig):
200200
local_experiment_root_dir,
201201
cfg.aggregate_cleanup,
202202
cfg.get("sketch_parameters", None),
203+
cfg.get("windowing", None),
203204
)
204205
)
205206
sync.rsync_controller_client_configs(

0 commit comments

Comments
 (0)