Skip to content

fix(fractional): support nested JSON Logic, boolean names, negative weight clamping, null key error#44

Open
aepfli wants to merge 3 commits intomainfrom
fix/fractional-nested-expressions
Open

fix(fractional): support nested JSON Logic, boolean names, negative weight clamping, null key error#44
aepfli wants to merge 3 commits intomainfrom
fix/fractional-nested-expressions

Conversation

@aepfli
Copy link
Copy Markdown
Member

@aepfli aepfli commented Mar 30, 2026

Summary

Three related fixes to the fractional operator uncovered by new testbed scenarios (flagd-testbed PRs #341-#357).

1. Evaluate inner bucket elements as JSON Logic

Previously, the outer [name_expr, weight_expr] array was evaluated but its inner elements were passed as-is to fractional(). Now each inner element is evaluated through the JSON Logic evaluator, enabling nested expressions as variant names/weights and boolean literals as bucket names.

2. Clamp negative weights to zero

Negative weights are now clamped to 0 so the bucket participates in the list but receives no traffic — matching expected spec behavior.

3. Return error on null bucket key expression

When the first argument is a JSON Logic expression that evaluates to null or non-string, return an error so the flag engine falls back to defaultVariant.

All existing tests pass with zero regressions. New unit tests added for each fix.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request enhances the fractional operator by allowing bucket names to be any JSON scalar (string, boolean, or number) and ensuring that nested JSON Logic within bucket definitions is evaluated. It also implements clamping for negative weights and refines the bucketing logic to handle zero-weight scenarios more gracefully. Review feedback recommends optimizing performance by avoiding an unnecessary clone of context data and refactoring the manual loop in the fractional function to use more idiomatic Rust iterators.

@github-actions github-actions bot mentioned this pull request Mar 16, 2026
aepfli and others added 2 commits March 30, 2026 17:44
…eight clamping, null key error

Three related fixes to the fractional operator:

1. Evaluate inner bucket elements as JSON Logic
   Previously bucket name/weight inner elements were taken as literal JSON
   values after the outer array was evaluated. Now each inner element is
   evaluated through the JSON Logic evaluator, enabling nested expressions:
     - [{'if': [{'==': [{'var': 'tier'}, 'premium']}, 'premium', 'standard']}, 50]
     - [{'var': 'color'}, 50]
   and boolean literals used when fractional is a condition:
     - [false, 0], [true, 100]

2. Clamp negative weights to zero
   Previously a negative weight triggered a hard error. Negative values are
   now clamped to 0 so the bucket participates in the name list but receives
   no traffic, matching the expected spec behavior.

3. Return error on null bucket key expression
   When the first argument is a JSON Logic expression that evaluates to null
   or a non-string value, return an error so the flag engine falls back to
   the defaultVariant. The existing implicit fallback (flagKey+targetingKey)
   is preserved only for array literals as the first argument (no-seed form).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
- Avoid unnecessary .clone() on context data by holding root reference
- Replace manual while-loop with idiomatic chunks(2) iterator

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
@aepfli aepfli force-pushed the fix/fractional-nested-expressions branch from 95582ba to 8506dc1 Compare March 30, 2026 15:45
Update two callers in integration_tests.rs that assumed fractional()
returned String — now it returns serde_json::Value.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Simon Schrottner <simon.schrottner@dynatrace.com>
@aepfli aepfli force-pushed the fix/fractional-nested-expressions branch from 8506dc1 to 8ae755d Compare March 30, 2026 15:45
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