Skip to content

refactor(types): split ExactKind::MinMax into Min and Max - #407

Merged
zzylol merged 3 commits into
feat/current-series-rulesfrom
refactor/split-min-max
Sep 13, 2026
Merged

refactor(types): split ExactKind::MinMax into Min and Max#407
zzylol merged 3 commits into
feat/current-series-rulesfrom
refactor/split-min-max

Conversation

@zzylol

@zzylol zzylol commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

The exact maximum accumulator was named MinMax, while minimum already used Min. Rename ExactKind::MinMax and ExactParams::MinMax to Max, updating mapping, schema, accuracy provenance, and tests.

Before this PR: the maximum family used the ambiguous MinMax name.

After this PR: minimum and maximum have explicit Min / Max variants. Nested count(distinct_over_time(...)) retains an outer Count over per-series Cardinality. For one series with samples [1, 2], the inner result is 2 and the outer count is 1. Regression coverage preserves both levels and grouping for ungrouped and by (job) queries.

Verification: 187 PromQL frontend tests passed; frontend all-target Clippy with -D warnings, formatting, and diff checks passed. A focused nested-count regression failed against the previous PR head before the correction. Production backend execution was not run for this update.

Base and compatibility: stacked on feat/current-series-rules, not main. The public enum rename requires downstream consumers to update their references and serialized contracts together.

zzylol and others added 2 commits September 13, 2026 09:38
`ExactKind::MinMax` was never a min/max pair: `function_rules` maps
`AggIntent::Max` onto it and `AggIntent::Min` onto the separately added
`ExactKind::Min`, so the name promised a two-sided accumulator that the
variant never was. Consumers that match on the family had to carry the
direction out-of-band (ASAPQuery-backend threads it through the
`aggregationSubType` wire string) because the name gave no guarantee
about which extremum the state holds.

Rename the variant to `Max` in both `ExactKind` and `ExactParams`, so
the two directions are symmetric variants and a stored minimum can no
longer content-address onto a maximum.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Lowering `count(v)` to a row count (15e6cf8) matched PromQL, but it left
no way to ask for a distinct count that reduces across series. The
`Cardinality` intent survived only under `distinct_over_time(v[w])`,
which is per-series: a consumer holding one mergeable cardinality state
per source could answer the merged question and had no expression that
asked it.

Collapse `count(distinct_over_time(v[w]))` into a single
`Aggregate{[Cardinality]}` reduced by the outer `by`. The nested reading
-- count the series that have a distinct-count -- is not what anyone
writes this expression for, and it discards the mergeability of the
state underneath.

The collapsed form needs its own reduction rule: `reduction_for` reads
the surviving `TimeRange` as one row per series and answers `PerEntity`,
which is right for a bare `distinct_over_time(v[w])` and wrong once an
explicit aggregator wraps it. `windowed_reduce` keeps the outer
aggregator's grouping, so an empty `by` reduces everything.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@zzylol
zzylol merged commit 9f41662 into feat/current-series-rules Sep 13, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant