Repository navigation
fix(flags): sort evaluation contexts in the Rust cache builder - #92164
Merged
Merged
Conversation
The Rust builder aggregated a flag's evaluation context names with a bare ARRAY_AGG, so Postgres returned them in join order. The Python builder uses ArrayAgg(distinct=True), which sorts and deduplicates. A flag with two or more contexts therefore got a different array from each builder, and the Rust build could differ from itself between runs. Add DISTINCT to the Rust aggregate so both sides emit array_agg(DISTINCT ...) and produce the same array. Python is the incumbent writer, so its ordering is the one every live cache entry already holds. Widen the two tests that could not catch this. The Rust one asserted membership rather than order. The Python one used a single-element array, where ordering cannot vary. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
😎 Merged successfully - details. |
Contributor
🤖 CI report
|
Contributor
|
Reviews (1): Last reviewed commit: "fix(flags): sort evaluation contexts in ..." | Re-trigger Greptile |
Contributor
There was a problem hiding this comment.
Approved.
Small, contained SQL fix aligning Rust's array aggregation with Python's existing sorted behavior in a cache-verification path with no production write path; author is on the owning team and tests were updated to pin the new behavior.
- Author wrote 0% of the modified lines and has 8 merged PRs in these paths (familiarity MODERATE).
- 👍 on the PR from greptile-apps[bot].
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 17L, 1F substantive, 30L/2F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T1-agent / T1b-small (30L, 2F, two-areas, fix) |
| stamphog 2.0.0b4 | .stamphog/policy.yml @ fbfdf40 · reviewed head fbfdf40 |
Member
Author
|
/trunk merge |
dmarticus
added a commit
that referenced
this pull request
Sep 4, 2026
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
dmarticus
added a commit
that referenced
this pull request
Sep 4, 2026
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
dmarticus
added a commit
that referenced
this pull request
Sep 4, 2026
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
JamesPatrickGill
added a commit
that referenced
this pull request
Sep 10, 2026
…laced A flag whose stored `filters` do not parse into `FlagFilters` is dropped by the Rust builder and kept by Python. #92163 landed the decision to count that drop rather than stop it, and added `test_flag_with_malformed_filters_is_dropped_and_counted` beside the builder to cover the counters. This file asserted the opposite, so it could only ever fail. The module doc now points at the test that owns the case, so the assertion does not come back. The golden comparison is unaffected and needed no regeneration. #92164 sorted the Rust evaluation-context aggregate, so the built payload now matches the golden that was already committed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Problem
evaluation_contextsfield mismatch.ArrayAgg(..., distinct=True), which Postgres renders asarray_agg(DISTINCT ...). That sorts them.ARRAY_AGGwith neitherDISTINCTnorORDER BY. Postgres guarantees no row order without one, so Rust returned join order, and could return a different order between runs.Changes
ARRAY_AGG(DISTINCT ctx.name), so both builders produce the same sorted array (rust/feature-flags/src/flags/feature_flag_list.rs).DISTINCTrather thanORDER BY ctx.name, so both sides run the identical construct and match by construction. The explicit sort looks stricter, but it would only go on the Rust side: four Python sites use the bareArrayAgg(..., distinct=True). If Postgres ever stopped sorting for aggregateDISTINCT, identical constructs break together and both tests go red, whereas a one-sidedORDER BYwould leave Rust sorted and Python not.How did you test this code?
test_fetch_flags_with_evaluation_tags_from_pgnow asserts the exact array. It already inserted three contexts out of alphabetical order, but asserted membership withcontains, so no ordering bug could fail it. On the old aggregate it fails with left["docs-page", "marketing-site", "app"]against right["app", "docs-page", "marketing-site"].test_verify_cache_detects_evaluation_context_renamemoves from one evaluation context to two, created out of alphabetical order. The single-element array it used could not vary in order. This case passes before and after, because the Python aggregate is unchanged. It catches a later removal ofdistinct=True, which would split the two builders again.cargo test -p feature-flagsfail locally before this change as well. They need a GeoIP database file and acohort_membershiptable the local database does not have. None reach this code path.Automatic notifications
Docs update
None. No documented behavior changes.
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Claude Code worked from a written brief that fixed the scope, the direction of the fix, and the build and test commands.
Skills invoked:
/writing-tests,/writing-code-comments,/writing-pr-descriptions,/review-code --fix.Two decisions are worth a reviewer's attention. The brief called for extending the Python test at
test_flags_cache.py, but that test cannot fail before the change, because it never runs the Rust query. The failing test is therefore the Rust one, and the Python case is widened only to pin the reference ordering. Separately, the review pass proposed an explicitORDER BYinside the aggregate; the Changes section records why that was declined.The review pass also corrected a comment that named one Python builder when there are two.
flags_hypercacheregisters both aload_fnand abatch_load_fn, and the single-team path inproducts/feature_flags/backend/models/feature_flag.pycarries a second copy of the sameArrayAgg. That copy is the one the cache verifier compares against.Follow-up not taken here: the same
ArrayAgg(..., distinct=True)is hand-rolled at four Python sites. A shared helper would give the Rust comment one symbol to point at, but it touches files this change does not otherwise edit.