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

Commit 9f0ca6c

Browse files
authored
Merge pull request #115 from launchdarkly/3.0.0
prepare 3.0.0 release
2 parents d3020cc + 0189ca0 commit 9f0ca6c

29 files changed

+1093
-642
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
version=2.6.0
1+
version=3.0.0
22
ossrhUsername=
33
ossrhPassword=

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

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import org.slf4j.Logger;
77
import org.slf4j.LoggerFactory;
88

9+
import static com.launchdarkly.client.VersionedDataKind.SEGMENTS;
10+
911
import java.util.List;
1012

1113
class Clause {
@@ -16,7 +18,17 @@ class Clause {
1618
private List<JsonPrimitive> values; //interpreted as an OR of values
1719
private boolean negate;
1820

19-
boolean matchesUser(LDUser user) {
21+
public Clause() {
22+
}
23+
24+
public Clause(String attribute, Operator op, List<JsonPrimitive> values, boolean negate) {
25+
this.attribute = attribute;
26+
this.op = op;
27+
this.values = values;
28+
this.negate = negate;
29+
}
30+
31+
boolean matchesUserNoSegments(LDUser user) {
2032
JsonElement userValue = user.getValueForEvaluation(attribute);
2133
if (userValue == null) {
2234
return false;
@@ -42,6 +54,26 @@ boolean matchesUser(LDUser user) {
4254
return false;
4355
}
4456

57+
boolean matchesUser(FeatureStore store, LDUser user) {
58+
// In the case of a segment match operator, we check if the user is in any of the segments,
59+
// and possibly negate
60+
if (op == Operator.segmentMatch) {
61+
for (JsonPrimitive j: values) {
62+
if (j.isString()) {
63+
Segment segment = store.get(SEGMENTS, j.getAsString());
64+
if (segment != null) {
65+
if (segment.matchesUser(user)) {
66+
return maybeNegate(true);
67+
}
68+
}
69+
}
70+
}
71+
return maybeNegate(false);
72+
}
73+
74+
return matchesUserNoSegments(user);
75+
}
76+
4577
private boolean matchAny(JsonPrimitive userValue) {
4678
for (JsonPrimitive v : values) {
4779
if (op.apply(userValue, v)) {
@@ -59,4 +91,4 @@ private boolean maybeNegate(boolean b) {
5991
}
6092

6193

62-
}
94+
}

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

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
import org.slf4j.Logger;
66
import org.slf4j.LoggerFactory;
77

8+
import static com.launchdarkly.client.VersionedDataKind.FEATURES;
9+
810
import java.lang.reflect.Type;
911
import java.util.ArrayList;
1012
import java.util.List;
1113
import java.util.Map;
1214

13-
class FeatureFlag {
15+
class FeatureFlag implements VersionedData {
1416
private final static Logger logger = LoggerFactory.getLogger(FeatureFlag.class);
1517

1618
private static final Type mapType = new TypeToken<Map<String, FeatureFlag>>() {
@@ -76,7 +78,7 @@ private JsonElement evaluate(LDUser user, FeatureStore featureStore, List<Featur
7678
boolean prereqOk = true;
7779
if (prerequisites != null) {
7880
for (Prerequisite prereq : prerequisites) {
79-
FeatureFlag prereqFeatureFlag = featureStore.get(prereq.getKey());
81+
FeatureFlag prereqFeatureFlag = featureStore.get(FEATURES, prereq.getKey());
8082
JsonElement prereqEvalResult = null;
8183
if (prereqFeatureFlag == null) {
8284
logger.error("Could not retrieve prerequisite flag: " + prereq.getKey() + " when evaluating: " + key);
@@ -100,12 +102,12 @@ private JsonElement evaluate(LDUser user, FeatureStore featureStore, List<Featur
100102
}
101103
}
102104
if (prereqOk) {
103-
return getVariation(evaluateIndex(user));
105+
return getVariation(evaluateIndex(user, featureStore));
104106
}
105107
return null;
106108
}
107109

108-
private Integer evaluateIndex(LDUser user) {
110+
private Integer evaluateIndex(LDUser user, FeatureStore store) {
109111
// Check to see if targets match
110112
if (targets != null) {
111113
for (Target target : targets) {
@@ -119,7 +121,7 @@ private Integer evaluateIndex(LDUser user) {
119121
// Now walk through the rules and see if any match
120122
if (rules != null) {
121123
for (Rule rule : rules) {
122-
if (rule.matchesUser(user)) {
124+
if (rule.matchesUser(store, user)) {
123125
return rule.variationIndexForUser(user, key, salt);
124126
}
125127
}
@@ -156,15 +158,15 @@ else if (index >= variations.size()) {
156158
}
157159
}
158160

159-
int getVersion() {
161+
public int getVersion() {
160162
return version;
161163
}
162164

163-
String getKey() {
165+
public String getKey() {
164166
return key;
165167
}
166168

167-
boolean isDeleted() {
169+
public boolean isDeleted() {
168170
return deleted;
169171
}
170172

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

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,31 @@
55
import org.slf4j.Logger;
66
import org.slf4j.LoggerFactory;
77

8+
import static com.launchdarkly.client.VersionedDataKind.FEATURES;
9+
import static com.launchdarkly.client.VersionedDataKind.SEGMENTS;
10+
811
import java.io.IOException;
12+
import java.util.HashMap;
913
import java.util.Map;
1014

1115
class FeatureRequestor {
1216
private static final Logger logger = LoggerFactory.getLogger(FeatureRequestor.class);
1317
private static final String GET_LATEST_FLAGS_PATH = "/sdk/latest-flags";
18+
private static final String GET_LATEST_SEGMENTS_PATH = "/sdk/latest-segments";
19+
private static final String GET_LATEST_ALL_PATH = "/sdk/latest-all";
1420
private final String sdkKey;
1521
private final LDConfig config;
1622

23+
static class AllData {
24+
final Map<String, FeatureFlag> flags;
25+
final Map<String, Segment> segments;
26+
27+
AllData(Map<String, FeatureFlag> flags, Map<String, Segment> segments) {
28+
this.flags = flags;
29+
this.segments = segments;
30+
}
31+
}
32+
1733
FeatureRequestor(String sdkKey, LDConfig config) {
1834
this.sdkKey = sdkKey;
1935
this.config = config;
@@ -29,6 +45,28 @@ FeatureFlag getFlag(String featureKey) throws IOException, InvalidSDKKeyExceptio
2945
return FeatureFlag.fromJson(config, body);
3046
}
3147

48+
Map<String, Segment> getAllSegments() throws IOException, InvalidSDKKeyException {
49+
String body = get(GET_LATEST_SEGMENTS_PATH);
50+
return Segment.fromJsonMap(config, body);
51+
}
52+
53+
Segment getSegment(String segmentKey) throws IOException, InvalidSDKKeyException {
54+
String body = get(GET_LATEST_SEGMENTS_PATH + "/" + segmentKey);
55+
return Segment.fromJson(config, body);
56+
}
57+
58+
AllData getAllData() throws IOException, InvalidSDKKeyException {
59+
String body = get(GET_LATEST_ALL_PATH);
60+
return config.gson.fromJson(body, AllData.class);
61+
}
62+
63+
static Map<VersionedDataKind<?>, Map<String, ? extends VersionedData>> toVersionedDataMap(AllData allData) {
64+
Map<VersionedDataKind<?>, Map<String, ? extends VersionedData>> ret = new HashMap<>();
65+
ret.put(FEATURES, allData.flags);
66+
ret.put(SEGMENTS, allData.segments);
67+
return ret;
68+
}
69+
3270
private String get(String path) throws IOException, InvalidSDKKeyException {
3371
Request request = config.getRequestBuilder(sdkKey)
3472
.url(config.baseURI.toString() + path)
@@ -64,4 +102,4 @@ public static class InvalidSDKKeyException extends Exception {
64102
public InvalidSDKKeyException() {
65103
}
66104
}
67-
}
105+
}

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

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,70 +4,73 @@
44
import java.util.Map;
55

66
/**
7-
* A thread-safe, versioned store for {@link FeatureFlag} objects.
8-
* Implementations should permit concurrent access and updates.
9-
*
7+
* A thread-safe, versioned store for feature flags and related objects received from the
8+
* streaming API. Implementations should permit concurrent access and updates.
9+
* <p>
1010
* Delete and upsert requests are versioned-- if the version number in the request is less than
11-
* the currently stored version of the feature, the request should be ignored.
12-
*
11+
* the currently stored version of the object, the request should be ignored.
12+
* <p>
1313
* These semantics support the primary use case for the store, which synchronizes a collection
14-
* of features based on update messages that may be received out-of-order.
15-
*
14+
* of objects based on update messages that may be received out-of-order.
15+
* @since 3.0.0
1616
*/
1717
public interface FeatureStore extends Closeable {
1818
/**
19-
*
20-
* Returns the {@link FeatureFlag} to which the specified key is mapped, or
21-
* null if the key is not associated or the associated {@link FeatureFlag} has
19+
* Returns the object to which the specified key is mapped, or
20+
* null if the key is not associated or the associated object has
2221
* been deleted.
2322
*
24-
* @param key the key whose associated {@link FeatureFlag} is to be returned
25-
* @return the {@link FeatureFlag} to which the specified key is mapped, or
26-
* null if the key is not associated or the associated {@link FeatureFlag} has
23+
* @param <T> class of the object that will be returned
24+
* @param kind the kind of object to get
25+
* @param key the key whose associated object is to be returned
26+
* @return the object to which the specified key is mapped, or
27+
* null if the key is not associated or the associated object has
2728
* been deleted.
2829
*/
29-
FeatureFlag get(String key);
30+
<T extends VersionedData> T get(VersionedDataKind<T> kind, String key);
3031

3132
/**
32-
* Returns a {@link java.util.Map} of all associated features.
33-
*
33+
* Returns a {@link java.util.Map} of all associated objects of a given kind.
3434
*
35-
* @return a map of all associated features.
35+
* @param <T> class of the objects that will be returned in the map
36+
* @param kind the kind of objects to get
37+
* @return a map of all associated object.
3638
*/
37-
Map<String, FeatureFlag> all();
39+
<T extends VersionedData> Map<String, T> all(VersionedDataKind<T> kind);
3840

3941
/**
40-
* Initializes (or re-initializes) the store with the specified set of features. Any existing entries
41-
* will be removed. Implementations can assume that this set of features is up to date-- there is no
42-
* need to perform individual version comparisons between the existing features and the supplied
42+
* Initializes (or re-initializes) the store with the specified set of objects. Any existing entries
43+
* will be removed. Implementations can assume that this set of objects is up to date-- there is no
44+
* need to perform individual version comparisons between the existing objects and the supplied
4345
* features.
4446
*
45-
*
46-
* @param features the features to set the store
47+
* @param allData all objects to be stored
4748
*/
48-
void init(Map<String, FeatureFlag> features);
49+
void init(Map<VersionedDataKind<?>, Map<String, ? extends VersionedData>> allData);
4950

5051
/**
51-
*
52-
* Deletes the feature associated with the specified key, if it exists and its version
52+
* Deletes the object associated with the specified key, if it exists and its version
5353
* is less than or equal to the specified version.
5454
*
55-
* @param key the key of the feature to be deleted
55+
* @param <T> class of the object to be deleted
56+
* @param kind the kind of object to delete
57+
* @param key the key of the object to be deleted
5658
* @param version the version for the delete operation
5759
*/
58-
void delete(String key, int version);
60+
<T extends VersionedData> void delete(VersionedDataKind<T> kind, String key, int version);
5961

6062
/**
61-
* Update or insert the feature associated with the specified key, if its version
62-
* is less than or equal to the version specified in the argument feature.
63+
* Update or insert the object associated with the specified key, if its version
64+
* is less than or equal to the version specified in the argument object.
6365
*
64-
* @param key
65-
* @param feature
66+
* @param <T> class of the object to be updated
67+
* @param kind the kind of object to update
68+
* @param item the object to update or insert
6669
*/
67-
void upsert(String key, FeatureFlag feature);
70+
<T extends VersionedData> void upsert(VersionedDataKind<T> kind, T item);
6871

6972
/**
70-
* Returns true if this store has been initialized
73+
* Returns true if this store has been initialized.
7174
*
7275
* @return true if this store has been initialized
7376
*/

0 commit comments

Comments
 (0)