Skip to content

Commit 5f3d3f0

Browse files
committed
fix: Include the big segments status on evaluation reasons for failed evaluations
A malformed flag error that occurs after a big segment query no longer drops the big segments status from the reason.
1 parent db17ab9 commit 5f3d3f0

2 files changed

Lines changed: 57 additions & 1 deletion

File tree

‎lib/sdk/server/src/main/java/com/launchdarkly/sdk/server/Evaluator.java‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,14 @@ EvalResult evaluate(FeatureFlag flag, LDContext context, @Nonnull EvaluationReco
163163
return result;
164164
} catch (EvaluationException e) {
165165
logger.error("Could not evaluate flag \"{}\": {}", flag.getKey(), e.getMessage());
166-
return EvalResult.error(e.errorKind);
166+
EvalResult result = EvalResult.error(e.errorKind);
167+
// A big segment query can run before the error occurs. Keep its status on the error reason.
168+
if (state.bigSegmentsStatus != null) {
169+
result = result.withReason(
170+
result.getReason().withBigSegmentsStatus(state.bigSegmentsStatus)
171+
);
172+
}
173+
return result;
167174
}
168175
}
169176

‎lib/sdk/server/src/test/java/com/launchdarkly/sdk/server/EvaluatorBigSegmentTest.java‎

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.launchdarkly.sdk.server;
22

3+
import com.launchdarkly.sdk.AttributeRef;
34
import com.launchdarkly.sdk.ContextKind;
5+
import com.launchdarkly.sdk.EvaluationReason;
46
import com.launchdarkly.sdk.EvaluationReason.BigSegmentsStatus;
57
import com.launchdarkly.sdk.LDContext;
68
import com.launchdarkly.sdk.LDValue;
@@ -14,6 +16,7 @@
1416
import static com.launchdarkly.sdk.server.Evaluator.makeBigSegmentRef;
1517
import static com.launchdarkly.sdk.server.EvaluatorTestUtil.expectNoPrerequisiteEvals;
1618
import static com.launchdarkly.sdk.server.ModelBuilders.booleanFlagWithClauses;
19+
import static com.launchdarkly.sdk.server.ModelBuilders.clause;
1720
import static com.launchdarkly.sdk.server.ModelBuilders.clauseMatchingContext;
1821
import static com.launchdarkly.sdk.server.ModelBuilders.clauseMatchingSegment;
1922
import static com.launchdarkly.sdk.server.ModelBuilders.flagBuilder;
@@ -192,4 +195,50 @@ public void bigSegmentStateIsQueriedOnlyOncePerKeyEvenIfFlagReferencesMultipleSe
192195
assertEquals(LDValue.of(true), result.getValue());
193196
assertEquals(BigSegmentsStatus.HEALTHY, result.getReason().getBigSegmentsStatus());
194197
}
198+
199+
@Test
200+
public void bigSegmentStatusIsIncludedWhenLaterClauseIsMalformed() {
201+
Segment segment = segmentBuilder("segmentkey").unbounded(true).generation(2).build();
202+
Clause malformedClause = clause(null, (AttributeRef)null, DataModel.Operator.in, LDValue.of("x"));
203+
FeatureFlag flag = flagBuilder("key")
204+
.on(true)
205+
.fallthroughVariation(0)
206+
.variations(false, true)
207+
.rules(
208+
ruleBuilder().variation(1).clauses(clauseMatchingSegment(segment)).build(),
209+
ruleBuilder().variation(1).clauses(malformedClause).build()
210+
)
211+
.build();
212+
213+
// The context is not in the big segment, so evaluation continues to the malformed rule.
214+
BigSegmentStoreWrapper.BigSegmentsQueryResult queryResult = new BigSegmentStoreWrapper.BigSegmentsQueryResult();
215+
queryResult.status = BigSegmentsStatus.STALE;
216+
queryResult.membership = createMembershipFromSegmentRefs(null, null);
217+
Evaluator evaluator = evaluatorBuilder().withStoredSegments(segment).withBigSegmentQueryResult(testUser.getKey(), queryResult).build();
218+
219+
EvalResult result = evaluator.evaluate(flag, testUser, expectNoPrerequisiteEvals());
220+
assertEquals(LDValue.ofNull(), result.getValue());
221+
assertEquals(EvaluationReason.ErrorKind.MALFORMED_FLAG, result.getReason().getErrorKind());
222+
assertEquals(BigSegmentsStatus.STALE, result.getReason().getBigSegmentsStatus());
223+
}
224+
225+
@Test
226+
public void bigSegmentStatusIsIncludedWhenLaterClauseIsMalformedAndNoProviderIsConfigured() {
227+
Segment segment = segmentBuilder("segmentkey").unbounded(true).generation(2).build();
228+
Clause malformedClause = clause(null, (AttributeRef)null, DataModel.Operator.in, LDValue.of("x"));
229+
FeatureFlag flag = flagBuilder("key")
230+
.on(true)
231+
.fallthroughVariation(0)
232+
.variations(false, true)
233+
.rules(
234+
ruleBuilder().variation(1).clauses(clauseMatchingSegment(segment)).build(),
235+
ruleBuilder().variation(1).clauses(malformedClause).build()
236+
)
237+
.build();
238+
Evaluator evaluator = evaluatorBuilder().withStoredSegments(segment).withBigSegmentQueryResult(testUser.getKey(), null).build();
239+
240+
EvalResult result = evaluator.evaluate(flag, testUser, expectNoPrerequisiteEvals());
241+
assertEquals(EvaluationReason.ErrorKind.MALFORMED_FLAG, result.getReason().getErrorKind());
242+
assertEquals(BigSegmentsStatus.NOT_CONFIGURED, result.getReason().getBigSegmentsStatus());
243+
}
195244
}

0 commit comments

Comments
 (0)