diff --git a/asap-tools/experiments/recommended_sketch_configs/recommended_sketch_configs.py b/asap-tools/experiments/recommended_sketch_configs/recommended_sketch_configs.py index d0ec7a87..a0b104e6 100644 --- a/asap-tools/experiments/recommended_sketch_configs/recommended_sketch_configs.py +++ b/asap-tools/experiments/recommended_sketch_configs/recommended_sketch_configs.py @@ -286,6 +286,16 @@ def generate( if not rows: skipped.append(f"{dataset}/{query_id}/{range_}: no recommendation") continue + # Experiment names carry no family, and sketch-bench emits one row per + # family per query kind, so a query id with both a keys and a values + # form has a CMS and a KLL row; the second would replace the first. + planner_rows = [r for r in rows if r["family"] in PLANNER_FAMILIES] + if len(planner_rows) > 1: + families = ", ".join(r["family"] for r in planner_rows) + raise ValueError( + f"{dataset}/{query_id}/{range_}: more than one planner family " + f"({families})" + ) for row in rows: if row["family"] not in PLANNER_FAMILIES: skipped.append( diff --git a/asap-tools/experiments/tests/test_recommended_sketch_configs.py b/asap-tools/experiments/tests/test_recommended_sketch_configs.py index 6b2b45ab..41ce2e92 100644 --- a/asap-tools/experiments/tests/test_recommended_sketch_configs.py +++ b/asap-tools/experiments/tests/test_recommended_sketch_configs.py @@ -177,6 +177,45 @@ def test_config_that_misses_target_is_skipped(self): self.assertEqual(configs, {}) self.assertIn("does not meet the target", skipped[0]) + def test_two_planner_families_for_one_query_raises(self): + # Experiment names carry no family, so the second row used to silently + # replace the first's config. + with self.assertRaisesRegex(ValueError, "google_2011/cpu_by_job_id/instant"): + rsc.generate( + [ + recommendation( + "google_2011", + "cpu_by_job_id", + "instant", + "cms", + "rows=3 cols=4096", + ), + recommendation( + "google_2011", "cpu_by_job_id", "instant", "kll", "k=200" + ), + ], + [("google_2011", "cpu_by_job_id", "instant")], + "/traces", + ) + + def test_two_planner_families_for_unselected_query_are_ignored(self): + # rt_p99_by_msname has keys and values forms, so sketch-bench emits CMS + # and KLL rows for it; that must not block the selected queries. + configs, _ = rsc.generate( + self.recommendations + + [ + recommendation( + "alibaba_v2022", "rt_p99_by_msname", "5m", "cms", "rows=3 cols=4096" + ), + recommendation( + "alibaba_v2022", "rt_p99_by_msname", "5m", "kll", "k=200" + ), + ], + [("google_2011", "cpu_by_job_id", "5m")], + "/traces", + ) + self.assertEqual(len(configs), 2) + class ComposeGeneratedConfigTest(unittest.TestCase): def test_recommended_config_overrides_config_yaml_sketch_parameters(self):