Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit fba773c

Browse files
authored
prepare 4.4.0 release (#140)
1 parent e94c24c commit fba773c

File tree

4 files changed

+74
-11
lines changed

4 files changed

+74
-11
lines changed

src/main/java/com/launchdarkly/client/FeatureFlagsState.java

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,16 @@ public class FeatureFlagsState {
3333
static class FlagMetadata {
3434
final Integer variation;
3535
final EvaluationReason reason;
36-
final int version;
37-
final boolean trackEvents;
36+
final Integer version;
37+
final Boolean trackEvents;
3838
final Long debugEventsUntilDate;
3939

40-
FlagMetadata(Integer variation, EvaluationReason reason, int version, boolean trackEvents,
40+
FlagMetadata(Integer variation, EvaluationReason reason, Integer version, boolean trackEvents,
4141
Long debugEventsUntilDate) {
4242
this.variation = variation;
4343
this.reason = reason;
4444
this.version = version;
45-
this.trackEvents = trackEvents;
45+
this.trackEvents = trackEvents ? Boolean.TRUE : null;
4646
this.debugEventsUntilDate = debugEventsUntilDate;
4747
}
4848

@@ -51,8 +51,8 @@ public boolean equals(Object other) {
5151
if (other instanceof FlagMetadata) {
5252
FlagMetadata o = (FlagMetadata)other;
5353
return Objects.equal(variation, o.variation) &&
54-
version == o.version &&
55-
trackEvents == o.trackEvents &&
54+
Objects.equal(version, o.version) &&
55+
Objects.equal(trackEvents, o.trackEvents) &&
5656
Objects.equal(debugEventsUntilDate, o.debugEventsUntilDate);
5757
}
5858
return false;
@@ -131,10 +131,12 @@ static class Builder {
131131
private Map<String, JsonElement> flagValues = new HashMap<>();
132132
private Map<String, FlagMetadata> flagMetadata = new HashMap<>();
133133
private final boolean saveReasons;
134+
private final boolean detailsOnlyForTrackedFlags;
134135
private boolean valid = true;
135136

136137
Builder(FlagsStateOption... options) {
137138
saveReasons = FlagsStateOption.hasOption(options, FlagsStateOption.WITH_REASONS);
139+
detailsOnlyForTrackedFlags = FlagsStateOption.hasOption(options, FlagsStateOption.DETAILS_ONLY_FOR_TRACKED_FLAGS);
138140
}
139141

140142
Builder valid(boolean valid) {
@@ -144,9 +146,14 @@ Builder valid(boolean valid) {
144146

145147
Builder addFlag(FeatureFlag flag, EvaluationDetail<JsonElement> eval) {
146148
flagValues.put(flag.getKey(), eval.getValue());
149+
final boolean flagIsTracked = flag.isTrackEvents() ||
150+
(flag.getDebugEventsUntilDate() != null && flag.getDebugEventsUntilDate() > System.currentTimeMillis());
151+
final boolean wantDetails = !detailsOnlyForTrackedFlags || flagIsTracked;
147152
FlagMetadata data = new FlagMetadata(eval.getVariationIndex(),
148-
saveReasons ? eval.getReason() : null,
149-
flag.getVersion(), flag.isTrackEvents(), flag.getDebugEventsUntilDate());
153+
(saveReasons && wantDetails) ? eval.getReason() : null,
154+
wantDetails ? flag.getVersion() : null,
155+
flag.isTrackEvents(),
156+
flag.getDebugEventsUntilDate());
150157
flagMetadata.put(flag.getKey(), data);
151158
return this;
152159
}

src/main/java/com/launchdarkly/client/FlagsStateOption.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ public String toString() {
2727
*/
2828
public static final FlagsStateOption WITH_REASONS = new FlagsStateOption("WITH_REASONS");
2929

30+
/**
31+
* Specifies that any flag metadata that is normally only used for event generation - such as flag versions and
32+
* evaluation reasons - should be omitted for any flag that does not have event tracking or debugging turned on.
33+
* This reduces the size of the JSON data if you are passing the flag state to the front end.
34+
* @since 4.4.0
35+
*/
36+
public static final FlagsStateOption DETAILS_ONLY_FOR_TRACKED_FLAGS = new FlagsStateOption("DETAILS_ONLY_FOR_TRACKED_FLAGS");
37+
3038
static boolean hasOption(FlagsStateOption[] options, FlagsStateOption option) {
3139
for (FlagsStateOption o: options) {
3240
if (o == option) {

src/test/java/com/launchdarkly/client/FeatureFlagsStateTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public void canConvertToJson() {
8989
String json = "{\"key1\":\"value1\",\"key2\":\"value2\"," +
9090
"\"$flagsState\":{" +
9191
"\"key1\":{" +
92-
"\"variation\":0,\"version\":100,\"reason\":{\"kind\":\"OFF\"},\"trackEvents\":false" +
92+
"\"variation\":0,\"version\":100,\"reason\":{\"kind\":\"OFF\"}" + // note, "trackEvents: false" is omitted
9393
"},\"key2\":{" +
9494
"\"variation\":1,\"version\":200,\"reason\":{\"kind\":\"FALLTHROUGH\"},\"trackEvents\":true,\"debugEventsUntilDate\":1000" +
9595
"}" +

src/test/java/com/launchdarkly/client/LDClientEvaluationTest.java

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ public void allFlagsStateReturnsState() throws Exception {
293293
String json = "{\"key1\":\"value1\",\"key2\":\"value2\"," +
294294
"\"$flagsState\":{" +
295295
"\"key1\":{" +
296-
"\"variation\":0,\"version\":100,\"trackEvents\":false" +
296+
"\"variation\":0,\"version\":100" +
297297
"},\"key2\":{" +
298298
"\"variation\":1,\"version\":200,\"trackEvents\":true,\"debugEventsUntilDate\":1000" +
299299
"}" +
@@ -350,7 +350,7 @@ public void allFlagsStateReturnsStateWithReasons() {
350350
String json = "{\"key1\":\"value1\",\"key2\":\"value2\"," +
351351
"\"$flagsState\":{" +
352352
"\"key1\":{" +
353-
"\"variation\":0,\"version\":100,\"reason\":{\"kind\":\"OFF\"},\"trackEvents\":false" +
353+
"\"variation\":0,\"version\":100,\"reason\":{\"kind\":\"OFF\"}" +
354354
"},\"key2\":{" +
355355
"\"variation\":1,\"version\":200,\"reason\":{\"kind\":\"FALLTHROUGH\"},\"trackEvents\":true,\"debugEventsUntilDate\":1000" +
356356
"}" +
@@ -361,6 +361,54 @@ public void allFlagsStateReturnsStateWithReasons() {
361361
assertEquals(expected, gson.toJsonTree(state));
362362
}
363363

364+
@Test
365+
public void allFlagsStateCanOmitDetailsForUntrackedFlags() {
366+
long futureTime = System.currentTimeMillis() + 1000000;
367+
FeatureFlag flag1 = new FeatureFlagBuilder("key1")
368+
.version(100)
369+
.trackEvents(false)
370+
.on(false)
371+
.offVariation(0)
372+
.variations(js("value1"))
373+
.build();
374+
FeatureFlag flag2 = new FeatureFlagBuilder("key2")
375+
.version(200)
376+
.trackEvents(true)
377+
.on(true)
378+
.fallthrough(fallthroughVariation(1))
379+
.variations(js("off"), js("value2"))
380+
.build();
381+
FeatureFlag flag3 = new FeatureFlagBuilder("key3")
382+
.version(300)
383+
.trackEvents(false)
384+
.debugEventsUntilDate(futureTime) // event tracking is turned on temporarily even though trackEvents is false
385+
.on(false)
386+
.offVariation(0)
387+
.variations(js("value3"))
388+
.build();
389+
featureStore.upsert(FEATURES, flag1);
390+
featureStore.upsert(FEATURES, flag2);
391+
featureStore.upsert(FEATURES, flag3);
392+
393+
FeatureFlagsState state = client.allFlagsState(user, FlagsStateOption.WITH_REASONS, FlagsStateOption.DETAILS_ONLY_FOR_TRACKED_FLAGS);
394+
assertTrue(state.isValid());
395+
396+
String json = "{\"key1\":\"value1\",\"key2\":\"value2\",\"key3\":\"value3\"," +
397+
"\"$flagsState\":{" +
398+
"\"key1\":{" +
399+
"\"variation\":0" + // note, version and reason are omitted, and so is trackEvents: false
400+
"},\"key2\":{" +
401+
"\"variation\":1,\"version\":200,\"reason\":{\"kind\":\"FALLTHROUGH\"},\"trackEvents\":true" +
402+
"},\"key3\":{" +
403+
"\"variation\":0,\"version\":300,\"reason\":{\"kind\":\"OFF\"},\"debugEventsUntilDate\":" + futureTime +
404+
"}" +
405+
"}," +
406+
"\"$valid\":true" +
407+
"}";
408+
JsonElement expected = gson.fromJson(json, JsonElement.class);
409+
assertEquals(expected, gson.toJsonTree(state));
410+
}
411+
364412
@Test
365413
public void allFlagsStateReturnsEmptyStateForNullUser() throws Exception {
366414
featureStore.upsert(FEATURES, flagWithValue("key", js("value")));

0 commit comments

Comments
 (0)