Skip to content

Commit cfd6feb

Browse files
committed
updated storage, localhost and tests
1 parent 56082ef commit cfd6feb

15 files changed

+747
-23
lines changed

client/src/main/java/io/split/client/HttpSplitChangeFetcher.java

+10-19
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ public SplitChange fetch(long since, long sinceRBS, FetchOptions options) {
7878
if (SPEC_VERSION.equals(SPEC_1_1) && (System.currentTimeMillis() - _lastProxyCheckTimestamp >= PROXY_CHECK_INTERVAL_MILLISECONDS_SS)) {
7979
_log.info("Switching to new Feature flag spec ({}) and fetching.", SPEC_1_3);
8080
SPEC_VERSION = SPEC_1_3;
81+
since = -1;
82+
sinceRBS = -1;
8183
}
8284
URI uri = buildURL(options, since, sinceRBS);
8385
response = _client.get(uri, options, null);
@@ -109,38 +111,27 @@ public SplitChange fetch(long since, long sinceRBS, FetchOptions options) {
109111
SplitChange splitChange = new SplitChange();
110112
if (SPEC_VERSION.equals(Spec.SPEC_1_1)) {
111113
splitChange.featureFlags = convertBodyToOldSpec(response.body());
112-
splitChange.ruleBasedSegments = createEmptyDTO();
114+
splitChange.ruleBasedSegments = ChangeDto.createEmptyDto();
113115
} else {
114116
splitChange = Json.fromJson(response.body(), SplitChange.class);
117+
if (SPEC_VERSION.equals(Spec.SPEC_1_3) && _lastProxyCheckTimestamp != 0) {
118+
splitChange.clearCache = true;
119+
_lastProxyCheckTimestamp = 0L;
120+
}
115121
}
116122
return splitChange;
117123
}
118124

119-
public Long getLastProxyCheckTimestamp() {
120-
return _lastProxyCheckTimestamp;
121-
}
122-
123-
public void setLastProxyCheckTimestamp(long lastProxyCheckTimestamp) {
124-
synchronized (_lock) {
125-
_lastProxyCheckTimestamp = lastProxyCheckTimestamp;
126-
}
127-
}
128-
129-
private ChangeDto<RuleBasedSegment> createEmptyDTO() {
130-
ChangeDto<RuleBasedSegment> dto = new ChangeDto<>();
131-
dto.d = new ArrayList<>();
132-
dto.t = -1;
133-
dto.s = -1;
134-
return dto;
135-
}
136125
private ChangeDto<Split> convertBodyToOldSpec(String body) {
137126
return Json.fromJson(body, SplitChangesOldPayloadDto.class).toChangeDTO();
138127
}
139128

140129
private URI buildURL(FetchOptions options, long since, long sinceRBS) throws URISyntaxException {
141130
URIBuilder uriBuilder = new URIBuilder(_target).addParameter(SPEC, "" + SPEC_VERSION);
142131
uriBuilder.addParameter(SINCE, "" + since);
143-
uriBuilder.addParameter(RB_SINCE, "" + sinceRBS);
132+
if (SPEC_VERSION.equals(SPEC_1_3)) {
133+
uriBuilder.addParameter(RB_SINCE, "" + sinceRBS);
134+
}
144135
if (!options.flagSetsFilter().isEmpty()) {
145136
uriBuilder.addParameter(SETS, "" + options.flagSetsFilter());
146137
}

client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package io.split.client;
22

3+
import com.google.gson.JsonObject;
34
import com.google.gson.stream.JsonReader;
45
import io.split.client.dtos.ChangeDto;
56
import io.split.client.dtos.SplitChange;
7+
import io.split.client.dtos.SplitChangesOldPayloadDto;
68
import io.split.client.utils.InputStreamProvider;
79
import io.split.client.utils.Json;
810
import io.split.client.utils.LocalhostSanitizer;
@@ -20,6 +22,8 @@
2022
import java.util.ArrayList;
2123
import java.util.Arrays;
2224

25+
import static io.split.client.utils.Json.fromJson;
26+
2327
public class JsonLocalhostSplitChangeFetcher implements SplitChangeFetcher {
2428

2529
private static final Logger _log = LoggerFactory.getLogger(JsonLocalhostSplitChangeFetcher.class);
@@ -37,13 +41,23 @@ public JsonLocalhostSplitChangeFetcher(InputStreamProvider inputStreamProvider)
3741
public SplitChange fetch(long since, long sinceRBS, FetchOptions options) {
3842
try {
3943
JsonReader jsonReader = new JsonReader(new BufferedReader(new InputStreamReader(_inputStreamProvider.get(), StandardCharsets.UTF_8)));
40-
SplitChange splitChange = Json.fromJson(jsonReader, SplitChange.class);
44+
if (checkOldSpec(new JsonReader(new BufferedReader(new InputStreamReader(_inputStreamProvider.get(), StandardCharsets.UTF_8))))) {
45+
SplitChange splitChange = new SplitChange();
46+
splitChange.featureFlags = Json.fromJson(jsonReader, SplitChangesOldPayloadDto.class).toChangeDTO();
47+
splitChange.ruleBasedSegments = ChangeDto.createEmptyDto();
48+
return splitChange;
49+
}
50+
SplitChange splitChange = fromJson(jsonReader, SplitChange.class);
4151
return processSplitChange(splitChange, since, sinceRBS);
4252
} catch (Exception e) {
4353
throw new IllegalStateException("Problem fetching splitChanges: " + e.getMessage(), e);
4454
}
4555
}
4656

57+
private boolean checkOldSpec(JsonReader jsonReader) {
58+
return Json.fromJson(jsonReader, JsonObject.class).has("splits");
59+
}
60+
4761
private SplitChange processSplitChange(SplitChange splitChange, long changeNumber, long changeNumberRBS) throws NoSuchAlgorithmException {
4862
SplitChange splitChangeToProcess = LocalhostSanitizer.sanitization(splitChange);
4963
// if the till is less than storage CN and different from the default till ignore the change

client/src/main/java/io/split/client/SplitClientConfig.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ public CustomHeaderDecorator customHeaderDecorator() {
413413
}
414414

415415
public boolean isRootURIOverriden() {
416-
return _endpoint == SDK_ENDPOINT;
416+
return _endpoint != SDK_ENDPOINT;
417417
}
418418

419419
public CustomHttpModule alternativeHTTPModule() { return _alternativeHTTPModule; }
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
package io.split.client.dtos;
22

3+
import java.util.ArrayList;
34
import java.util.List;
45

56
public class ChangeDto<T> {
67
public long s;
78
public long t;
89
public List<T> d;
10+
11+
public static ChangeDto createEmptyDto() {
12+
ChangeDto dto = new ChangeDto<>();
13+
dto.d = new ArrayList<>();
14+
dto.t = -1;
15+
dto.s = -1;
16+
return dto;
17+
}
918
}

client/src/main/java/io/split/client/dtos/SplitChange.java

+1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ public class SplitChange {
77
public ChangeDto<Split> featureFlags;
88
@SerializedName("rbs")
99
public ChangeDto<RuleBasedSegment> ruleBasedSegments;
10+
public boolean clearCache;
1011
}

client/src/main/java/io/split/engine/experiments/SplitFetcherImp.java

+8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.split.engine.experiments;
22

3+
import io.split.Spec;
34
import io.split.client.dtos.ChangeDto;
45
import io.split.client.dtos.RuleBasedSegment;
56
import io.split.client.dtos.Split;
@@ -20,6 +21,7 @@
2021
import java.util.Set;
2122

2223
import static com.google.common.base.Preconditions.checkNotNull;
24+
import static io.split.Spec.SPEC_VERSION;
2325
import static io.split.client.utils.FeatureFlagProcessor.processFeatureFlagChanges;
2426
import static io.split.client.utils.RuleBasedSegmentProcessor.processRuleBasedSegmentChanges;
2527

@@ -124,6 +126,11 @@ private Set<String> runWithoutExceptionHandling(FetchOptions options) throws Int
124126
throw new IllegalStateException("SplitChange was null");
125127
}
126128

129+
if (change.clearCache) {
130+
_splitCacheProducer.clear();
131+
_ruleBasedSegmentCacheProducer.clear();
132+
}
133+
127134
if (checkExitConditions(change.featureFlags, _splitCacheProducer.getChangeNumber()) ||
128135
checkExitConditions(change.ruleBasedSegments, _ruleBasedSegmentCacheProducer.getChangeNumber())) {
129136
return segments;
@@ -149,6 +156,7 @@ private Set<String> runWithoutExceptionHandling(FetchOptions options) throws Int
149156
// some other thread may have updated the shared state. exit
150157
return segments;
151158
}
159+
152160
FeatureFlagsToUpdate featureFlagsToUpdate = processFeatureFlagChanges(_parser, change.featureFlags.d, _flagSetsFilter);
153161
segments = featureFlagsToUpdate.getSegments();
154162
_splitCacheProducer.update(featureFlagsToUpdate.getToAdd(), featureFlagsToUpdate.getToRemove(), change.featureFlags.t);

client/src/main/java/io/split/storages/RuleBasedSegmentCacheProducer.java

+1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ public interface RuleBasedSegmentCacheProducer extends RuleBasedSegmentCacheCom
88
boolean remove(String name);
99
void setChangeNumber(long changeNumber);
1010
void update(List<ParsedRuleBasedSegment> toAdd, List<String> toRemove, long changeNumber);
11+
void clear();
1112
}

client/src/main/java/io/split/storages/memory/InMemoryCacheImp.java

+2
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,9 @@ public void kill(String splitName, String defaultTreatment, long changeNumber) {
140140
@Override
141141
public void clear() {
142142
_concurrentMap.clear();
143+
_changeNumber.set(-1);
143144
_concurrentTrafficTypeNameSet.clear();
145+
_flagSets.clear();
144146
}
145147

146148
@Override

client/src/main/java/io/split/storages/memory/RuleBasedSegmentCacheInMemoryImp.java

+2
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ public List<String> ruleBasedSegmentNames() {
7171
return ruleBasedSegmentNamesList;
7272
}
7373

74+
@Override
7475
public void clear() {
76+
_changeNumber.set(-1);
7577
_concurrentMap.clear();
7678
}
7779

client/src/main/java/io/split/storages/pluggable/adapters/UserCustomRuleBasedSegmentAdapterProducer.java

+5
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ public void setChangeNumber(long changeNumber) {
4444
//NoOp
4545
}
4646

47+
@Override
48+
public void clear() {
49+
//NoOp
50+
}
51+
4752
@Override
4853
public void update(List<ParsedRuleBasedSegment> toAdd, List<String> toRemove, long changeNumber) {
4954
//NoOp

client/src/test/java/io/split/client/HttpSplitChangeFetcherTest.java

-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,6 @@ public void testSwitchingToOldSpec() throws URISyntaxException, InvocationTarget
262262
Assert.assertEquals(0, change.ruleBasedSegments.d.size());
263263
Assert.assertEquals(-1, change.ruleBasedSegments.s);
264264
Assert.assertEquals(-1, change.ruleBasedSegments.t);
265-
Assert.assertTrue(fetcher.getLastProxyCheckTimestamp() > 0);
266265

267266
// Set proxy interval to low number to force check for spec 1.3
268267
Field proxyInterval = fetcher.getClass().getDeclaredField("PROXY_CHECK_INTERVAL_MILLISECONDS_SS");

client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java

+19
Original file line numberDiff line numberDiff line change
@@ -201,4 +201,23 @@ public void processTestForException() {
201201

202202
SplitChange splitChange = localhostSplitChangeFetcher.fetch(-1L, -1, fetchOptions);
203203
}
204+
205+
@Test
206+
public void testParseOldSpec() throws FileNotFoundException {
207+
InputStream inputStream = new FileInputStream("src/test/resources/split_old_spec.json");
208+
InputStreamProvider inputStreamProvider = new StaticContentInputStreamProvider(inputStream);
209+
JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider);
210+
FetchOptions fetchOptions = Mockito.mock(FetchOptions.class);
211+
212+
SplitChange splitChange = localhostSplitChangeFetcher.fetch(-1L, -1, fetchOptions);
213+
214+
List<Split> split = splitChange.featureFlags.d;
215+
Assert.assertEquals(7, split.size());
216+
Assert.assertEquals(1660326991072L, splitChange.featureFlags.t);
217+
Assert.assertEquals(-1L, splitChange.featureFlags.s);
218+
219+
Assert.assertEquals(new ArrayList<>(), splitChange.ruleBasedSegments.d);
220+
Assert.assertEquals(-1L, splitChange.ruleBasedSegments.t);
221+
Assert.assertEquals(-1L, splitChange.ruleBasedSegments.s);
222+
}
204223
}

client/src/test/java/io/split/client/JsonLocalhostSplitFactoryTest.java

+17
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,21 @@ public void works() throws IOException, URISyntaxException, InterruptedException
3232
Assert.assertEquals("on_whitelist", client.getTreatment("admin", "push_test"));
3333
client.destroy();
3434
}
35+
36+
@Test
37+
public void testOldSpec() throws IOException, URISyntaxException, InterruptedException, TimeoutException {
38+
SplitClientConfig config = SplitClientConfig.builder()
39+
.splitFile("src/test/resources/split_old_spec.json")
40+
.segmentDirectory("src/test/resources")
41+
.setBlockUntilReadyTimeout(10000)
42+
.build();
43+
SplitFactory splitFactory = SplitFactoryBuilder.build("localhost", config);
44+
SplitClient client = splitFactory.client();
45+
client.blockUntilReady();
46+
47+
Assert.assertEquals("on", client.getTreatment("bilal", "split_1"));
48+
Assert.assertEquals("off", client.getTreatment("bilal", "split_2"));
49+
Assert.assertEquals("v5", client.getTreatment("admin", "split_2"));
50+
client.destroy();
51+
}
3552
}

0 commit comments

Comments
 (0)