Repository navigation
feat: Add the override marker to the flag and segment models and mark evaluations - #221
kinyoklion wants to merge 3 commits into
Conversation
f0038ed to
79250a7
Compare
1ba722a to
996b8d3
Compare
|
bugbot review |
996b8d3 to
ca22bc0
Compare
|
bugbot review |
|
bugbot review |
… evaluations The OVERRIDE specification requires an evaluation to be marked as override-affected when any definition it read carried the override marker: the evaluated flag, a prerequisite at any depth, or a segment consulted during matching, whether or not the segment matched. The marking propagates upward only. A prerequisite's own record reflects only the definitions that its own subtree read. An evaluation that fails is still marked when it read a marked definition. DataModel.FeatureFlag and DataModel.Segment carry a transient isOverride marker that is never serialized and never read from JSON, with a markedAsOverride() shallow copy that the override layer will use without modifying the source's entity. The evaluator tracks the marking per evaluation scope: the scope starts from its own flag's marker, each segment read can set it, and the value is saved, reset to the prerequisite's marker, and restored around each prerequisite evaluation. The result and every prerequisite record carry the marking on their reason. EvalResult exposes isOverrideAffected() and withOverrideAffected(), which copies rather than mutating the shared precomputed results. A requested-type mismatch keeps the marking on its error reason. The server SDK now depends on launchdarkly-java-sdk-common 2.6.0, which adds the overrideAffected indicator to EvaluationReason. CI for this change cannot pass until that version is released. Flag overrides are currently experimental and subject to change.
…gnized stage migrationVariation replaces the result of a flag that serves an unrecognized stage with a WRONG_TYPE error. The evaluation read the same definitions, so the replacement keeps the override-affected marking, as the type mismatch of an ordinary variation call already does, and the migration tracker receives a marked reason for an overridden flag.
When the evaluation of a flag throws, the error result now carries the override-affected marking of the flag's own definition, which was read before the failure. The spec marks a failed evaluation when a definition it read came from the override store.
64740d7 to
a4d9c28
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a4d9c28. Configure here.
| boolean overrideAffected = featureFlag != null && featureFlag.isOverride(); | ||
| return new EvalResultAndFlag( | ||
| EvalResult.of(defaultValue, NO_VARIATION, EvaluationReason.exception(e)).withOverrideAffected(overrideAffected), | ||
| null); |
There was a problem hiding this comment.
allFlagsState drops override on throw
Low Severity
A thrown evaluation is marked from the flag's own override marker on the single-flag path, but allFlagsState still builds an unmarked EXCEPTION reason. A store fault while reading a prerequisite or segment after getAll therefore omits overrideAffected for an override flag in the snapshot.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit a4d9c28. Configure here.


Summary
The OVERRIDE specification requires an evaluation to be marked as override-affected when any definition it read carried the override marker: the evaluated flag, a prerequisite at any depth, or a segment consulted during matching, whether or not the segment matched. The marking propagates upward only: a prerequisite's own record reflects only the definitions that its own subtree read, while the evaluation that requested it accumulates the result. An evaluation that fails is still marked when it read a marked definition, and a requested-type mismatch keeps the marking on its error reason, as does the WRONG_TYPE error that
migrationVariationreturns for an unrecognized stage.DataModel.FeatureFlagandDataModel.Segmentcarry a transientisOverridemarker. It is never serialized and never read from JSON.markedAsOverride()returns a shallow copy with the marker set, sharing nested collections and preprocessing with the source and never modifying it. The override layer will use it in the next change.EvalResult.isOverrideAffected()reads the reason's indicator, andwithOverrideAffected(boolean)returns a copy so that the shared precomputed results are never mutated.EXCEPTIONresult marked with the evaluated flag's own marker, because that definition was read before the failure.EvaluationReason.isOverrideAffected()and theoverrideAffectedJSON property (written only when true). CI for this change cannot pass until that version is released.Flag overrides are currently experimental and subject to change.
This PR is based on the file data reliability branch (rlamb/overrides-java-filedata-reloader) so the series applies in order; retarget it to feat/overrides once that branch merges.
The existing file data source keeps its current behavior; this change does not touch its code paths.
SDK-3246
Note
Overview
Adds experimental flag override support by tagging local override definitions and surfacing that on evaluation results, ahead of the override store layer in a follow-up PR.
Data model:
FeatureFlagandSegmentget a transientisOverrideflag (not in JSON) plusmarkedAsOverride()shallow copies for the override layer to use.Evaluation: The evaluator tracks whether the scope read any marked flag, prerequisite subtree, or segment (including when a segment does not match). That flows into
EvaluationReasonviaEvalResult.isOverrideAffected()/withOverrideAffected()without mutating shared precomputed results.InputValidatingEvaluatorandMigrationStageEnforcingEvaluatorpreserve the marker on type errors, exceptions, and malformed results;allFlagsStateexposes it per flag when reasons are requested.Dependency: Bumps
launchdarkly-java-sdk-commonto 2.6.0 forEvaluationReason.isOverrideAffected()and related APIs.Reviewed by Cursor Bugbot for commit a4d9c28. Bugbot is set up for automated code reviews on this repo. Configure here.
Opened from termag