diff --git a/crates/asap_types/src/capability_matching.rs b/crates/asap_types/src/capability_matching.rs index 3ddd270e..57330399 100644 --- a/crates/asap_types/src/capability_matching.rs +++ b/crates/asap_types/src/capability_matching.rs @@ -235,11 +235,18 @@ pub fn compatible_agg_types(stat: Statistic) -> &'static [AggregationType] { // signed-counter matrix). `CountSketchAccumulator` answers // `Statistic::Topk` directly — see // `precompute_operators/count_sketch_accumulator.rs:284`. - // Without CountSketch listed here, `topk(K, top_endpoint_qps)` - // capability-misses and the warm engine returns `status=error`. + // `CountSketchWithHeap` is the explicit heap-bearing variant + // that also satisfies Topk through the heap directly + // (parallel to `CountMinSketchWithHeap`); the analyzer's + // `topk(...)` candidate returns `FrequencyTopk(Any)` so + // either heap-bearing variant matches. + // Without CountSketch / CountSketchWithHeap listed here, + // `topk(K, top_endpoint_qps)` capability-misses and the + // warm engine returns `status=error`. Statistic::Topk => &[ AggregationType::CountMinSketchWithHeap, AggregationType::CountSketch, + AggregationType::CountSketchWithHeap, ], } } diff --git a/crates/promql_utilities/src/query_logics/logics.rs b/crates/promql_utilities/src/query_logics/logics.rs index 8aa4c4c3..9772c18f 100644 --- a/crates/promql_utilities/src/query_logics/logics.rs +++ b/crates/promql_utilities/src/query_logics/logics.rs @@ -101,6 +101,12 @@ pub fn does_precompute_operator_support_subpopulations( // CountMinSketchWithHeap is only supported for Topk — does not support subpopulations AggregationType::CountMinSketchWithHeap if matches!(statistic, Statistic::Topk) => false, + // CountSketch is the signed-counter equivalent of CMS — same + // subpopulation shape for Sum/Count statistics. The + // heap-bearing variant covers Topk like its CMS counterpart. + AggregationType::CountSketch => matches!(statistic, Statistic::Sum | Statistic::Count), + AggregationType::CountSketchWithHeap if matches!(statistic, Statistic::Topk) => false, + // Default: not supported _ => panic!("Unexpected precompute operator: {}", precompute_operator), } @@ -186,6 +192,28 @@ mod tests { Statistic::Sum, AggregationType::CountMinSketch, )); + + // Sibling CountSketch path — must not panic, matches + // CountMinSketch's Sum/Count subpopulation shape. + assert!(does_precompute_operator_support_subpopulations( + Statistic::Sum, + AggregationType::CountSketch, + )); + assert!(does_precompute_operator_support_subpopulations( + Statistic::Count, + AggregationType::CountSketch, + )); + + // Heap-bearing variants on Topk — both return false (heap + // is per-policy, not subpopulation-keyed) and must not panic. + assert!(!does_precompute_operator_support_subpopulations( + Statistic::Topk, + AggregationType::CountMinSketchWithHeap, + )); + assert!(!does_precompute_operator_support_subpopulations( + Statistic::Topk, + AggregationType::CountSketchWithHeap, + )); } #[test]