Repository navigation
Range queries over Sliding-window aggregations use overlap-scan fetch, not exact-window fetch #608
Description
finish_range_context (asap-query-engine/src/engines/simple_engine/promql.rs:615) unconditionally sets extended_store_plan.values_query.is_exact_query = false, regardless of the aggregation's actual WindowType. This is the bug named in #580 (closed by #582) and re-flagged as still-live in a comment on #581 — #582's changes never touched this line.
Effect: a PromQL range query over a Sliding-window aggregation is routed to the overlap-scan fetch (query_precomputed_output) instead of the exact-window fetch (query_precomputed_output_exact), then merged downstream as if it were Tumbling (window_type = if is_exact_query { Sliding } else { Tumbling }, mod.rs:558) — wrong values, silently, no error. Instant queries don't have this bug: create_store_query_plan correctly derives is_exact_query = window_type == WindowType::Sliding (mod.rs:427).
Fix
Route Sliding-window range queries through query_precomputed_output_exact, once per output step, deriving each step's exact window bounds from the value aggregation's AggregationConfig (window_size_ms) the same way the instant path already does for its single window. Tumbling stays on the scan call (query_precomputed_output) unchanged — it's already correct, and (per #607) the scan call is read-locked while exact-query is currently write-locked, so there's no reason to move Tumbling off it.
Concretely, this likely means:
execute_range_query_pipeline's per-step loop (mod.rs:1541+) gains a Sliding-specific branch: instead of pulling from a single wideall_datafetch +bucket_mapwindow-scan (today's Tumbling-shaped approach), each step computes its exact window and callsexecute_store_querywith an exact-modeStoreQueryParamsfor that step.- Depends on MutableEpoch::exact_query requires a write lock, serializing concurrent queries #607 landing first (or at least being scoped) if this fix would otherwise multiply write-lock acquisitions across every output step of a Sliding range query — MutableEpoch::exact_query requires a write lock, serializing concurrent queries #607 removes that cost.
- Naturally wants # (batched exact-query API) to avoid N sequential store round-trips per range query, but is not blocked on it — N sequential exact calls is a valid, correct first cut.
On is_exact_query itself
A comment on #581 proposed removing is_exact_query as a threaded bool entirely once this is fixed, to eliminate "one more place the two paths can independently drift." Worth revisiting the field's shape as part of this fix (e.g., mirror the derivation in one shared helper called by both create_store_query_plan and finish_range_context), but note the keys-side query (create_keys_query_params) deliberately hardcodes exact=false regardless of the key aggregation's WindowType ("keys always use range queries") — any refactor of this field must preserve that as an explicit, named choice, not something a blanket "derive from WindowType" rule would get right by accident.
Testing
Per project convention: TDD. Write a RED test first that pins today's actual bug (a range query over a Sliding-window aggregation returns wrong values / wrong window composition), then fix.
Related: #581 (broader instant/range fetch-merge unification — this is one of the "must fix before/during step 4" items called out there), #580 (originally named this, incompletely fixed by #582), #607 (removes the write-lock cost this fix would otherwise multiply).
Activity
milindsrivastava1997 commentedon Aug 26, 2026
While reworking the store-query fetch path (query_precomputed_output vs query_precomputed_output_exact, #609/#613-adjacent), added two RED tests that pin exactly this bug — both currently
#[ignore = "known bug, see #608"]:range_query_sliding_multi_step_off_grid_windows_no_double_count_or_drop(window_size=3000, slide=1000)range_query_sliding_overlap_shifts_correctly_across_steps(window_size=2000, slide=1000)Both in
asap-query-engine/src/tests/exact_window_grid_adversarial_tests.rs. Confirmed root cause matches this issue's description exactly:execute_range_query_pipeline's per-stepscan_windowcall (mod.rs:1919) steps bytumbling_window_ms(==bucket_step_ms, i.e.slide_interval_msfor Sliding) across awindow_size_ms-wide lookback, summing whatever bucket it finds at each of thewindow_size_ms / slide_interval_msslide-grid positions. That's correct for genuine Tumbling multi-bucket merge (each entry found is a distinct non-overlapping bucket), but wrong for Sliding: each stored entry there is already a fullwindow_size_ms-wide pre-merged window (matchingworker.rs::merge_panes_for_window's real output shape), so summing several of them over-counts — observed directly: expected111.0, got12321.0(= 111+1110+11100, three overlapping windows summed instead of one).Un-ignore both tests once this is fixed; their asserted values were computed by hand from the correct per-step window composition.
refactor(query-engine): fetch non-exact store queries via a window-gr…
refactor(query-engine): dedupe Sliding/Tumbling branch, assert lookba…
refactor(query-engine): remove is_exact_query as a threaded bool (#628)