Skip to content

Commit 3ad6db9

Browse files
committed
Added old spec support in splitfetcher
1 parent daa9e4a commit 3ad6db9

File tree

5 files changed

+158
-42
lines changed

5 files changed

+158
-42
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ private Spec() {
88

99
// TODO: Change the schema to 1.3 when updating splitclient
1010
public static final String SPEC_1_3 = "1.3";
11+
public static final String SPEC_1_2 = "1.2";
1112
public static final String SPEC_1_1 = "1.1";
1213
public static String SPEC_VERSION = SPEC_1_3;
1314
}

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

Lines changed: 71 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package io.split.client;
22

33
import com.google.common.annotations.VisibleForTesting;
4+
import com.google.gson.JsonObject;
45

6+
import io.split.Spec;
57
import io.split.client.dtos.SplitChange;
68
import io.split.client.dtos.SplitHttpResponse;
79
import io.split.client.exceptions.UriTooLongException;
@@ -23,32 +25,40 @@
2325

2426
import static com.google.common.base.Preconditions.checkNotNull;
2527
import static io.split.Spec.SPEC_VERSION;
28+
import static io.split.Spec.SPEC_1_3;
29+
import static io.split.Spec.SPEC_1_2;
2630

2731
/**
2832
* Created by adilaijaz on 5/30/15.
2933
*/
3034
public final class HttpSplitChangeFetcher implements SplitChangeFetcher {
3135
private static final Logger _log = LoggerFactory.getLogger(HttpSplitChangeFetcher.class);
3236

37+
private final Object _lock = new Object();
3338
private static final String SINCE = "since";
3439
private static final String RB_SINCE = "rbSince";
3540
private static final String TILL = "till";
3641
private static final String SETS = "sets";
3742
private static final String SPEC = "s";
43+
private int PROXY_CHECK_INTERVAL_MINUTES_SS = 24 * 60;
44+
private Long _lastProxyCheckTimestamp = 0L;
3845
private final SplitHttpClient _client;
3946
private final URI _target;
4047
private final TelemetryRuntimeProducer _telemetryRuntimeProducer;
48+
private final boolean _rootURIOverriden;
4149

42-
public static HttpSplitChangeFetcher create(SplitHttpClient client, URI root, TelemetryRuntimeProducer telemetryRuntimeProducer)
50+
public static HttpSplitChangeFetcher create(SplitHttpClient client, URI root, TelemetryRuntimeProducer telemetryRuntimeProducer,
51+
boolean rootURIOverriden)
4352
throws URISyntaxException {
44-
return new HttpSplitChangeFetcher(client, Utils.appendPath(root, "api/splitChanges"), telemetryRuntimeProducer);
53+
return new HttpSplitChangeFetcher(client, Utils.appendPath(root, "api/splitChanges"), telemetryRuntimeProducer, rootURIOverriden);
4554
}
4655

47-
private HttpSplitChangeFetcher(SplitHttpClient client, URI uri, TelemetryRuntimeProducer telemetryRuntimeProducer) {
56+
private HttpSplitChangeFetcher(SplitHttpClient client, URI uri, TelemetryRuntimeProducer telemetryRuntimeProducer, boolean rootURIOverriden) {
4857
_client = client;
4958
_target = uri;
5059
checkNotNull(_target);
5160
_telemetryRuntimeProducer = checkNotNull(telemetryRuntimeProducer);
61+
_rootURIOverriden = rootURIOverriden;
5262
}
5363

5464
long makeRandomTill() {
@@ -59,27 +69,68 @@ long makeRandomTill() {
5969
@Override
6070
public SplitChange fetch(long since, long sinceRBS, FetchOptions options) {
6171
long start = System.currentTimeMillis();
62-
try {
63-
URI uri = buildURL(options, since, sinceRBS);
64-
SplitHttpResponse response = _client.get(uri, options, null);
65-
66-
if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) {
67-
if (response.statusCode() == HttpStatus.SC_REQUEST_URI_TOO_LONG) {
68-
_log.error("The amount of flag sets provided are big causing uri length error.");
69-
throw new UriTooLongException(String.format("Status code: %s. Message: %s", response.statusCode(), response.statusMessage()));
72+
SplitHttpResponse response;
73+
while (true) {
74+
try {
75+
if (SPEC_VERSION.equals(SPEC_1_2) && (System.currentTimeMillis() - _lastProxyCheckTimestamp >= PROXY_CHECK_INTERVAL_MINUTES_SS)) {
76+
_log.info("Switching to new Feature flag spec ({}) and fetching.", SPEC_1_3);
77+
SPEC_VERSION = SPEC_1_3;
7078
}
79+
URI uri = buildURL(options, since, sinceRBS);
80+
response = _client.get(uri, options, null);
81+
if (response.statusCode() < HttpStatus.SC_OK || response.statusCode() >= HttpStatus.SC_MULTIPLE_CHOICES) {
82+
if (response.statusCode() == HttpStatus.SC_REQUEST_URI_TOO_LONG) {
83+
_log.error("The amount of flag sets provided are big causing uri length error.");
84+
throw new UriTooLongException(String.format("Status code: %s. Message: %s", response.statusCode(), response.statusMessage()));
85+
}
7186

72-
_telemetryRuntimeProducer.recordSyncError(ResourceEnum.SPLIT_SYNC, response.statusCode());
73-
throw new IllegalStateException(
74-
String.format("Could not retrieve splitChanges since %s; http return code %s", since, response.statusCode())
75-
);
87+
if (response.statusCode() == HttpStatus.SC_BAD_REQUEST && SPEC_VERSION.equals(Spec.SPEC_1_3) && _rootURIOverriden) {
88+
SPEC_VERSION = Spec.SPEC_1_2;
89+
_log.warn("Detected proxy without support for Feature flags spec {} version, will switch to spec version {}",
90+
SPEC_1_3, SPEC_1_2);
91+
_lastProxyCheckTimestamp = System.currentTimeMillis();
92+
continue;
93+
}
94+
95+
_telemetryRuntimeProducer.recordSyncError(ResourceEnum.SPLIT_SYNC, response.statusCode());
96+
throw new IllegalStateException(
97+
String.format("Could not retrieve splitChanges since %s; http return code %s", since, response.statusCode())
98+
);
99+
}
100+
break;
101+
} catch (Exception e) {
102+
throw new IllegalStateException(String.format("Problem fetching splitChanges since %s: %s", since, e), e);
103+
} finally {
104+
_telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.SPLITS, System.currentTimeMillis() - start);
76105
}
77-
return Json.fromJson(response.body(), SplitChange.class);
78-
} catch (Exception e) {
79-
throw new IllegalStateException(String.format("Problem fetching splitChanges since %s: %s", since, e), e);
80-
} finally {
81-
_telemetryRuntimeProducer.recordSyncLatency(HTTPLatenciesEnum.SPLITS, System.currentTimeMillis() - start);
82106
}
107+
108+
String body = response.body();
109+
if (SPEC_VERSION.equals(Spec.SPEC_1_2)) {
110+
body = convertBodyToOldSpec(body);
111+
_lastProxyCheckTimestamp = System.currentTimeMillis();
112+
}
113+
return Json.fromJson(body, SplitChange.class);
114+
}
115+
116+
public Long getLastProxyCheckTimestamp() {
117+
return _lastProxyCheckTimestamp;
118+
}
119+
120+
public void setLastProxyCheckTimestamp(long lastProxyCheckTimestamp) {
121+
synchronized (_lock) {
122+
_lastProxyCheckTimestamp = lastProxyCheckTimestamp;
123+
}
124+
}
125+
126+
private String convertBodyToOldSpec(String body) {
127+
JsonObject targetBody = Json.fromJson("{\"ff\": {\"t\":-1, \"s\": -1}," +
128+
"\"rbs\": {\"d\":[], \"t\":-1, \"s\": -1}}", JsonObject.class);
129+
JsonObject jsonBody = Json.fromJson(body, JsonObject.class);
130+
targetBody.getAsJsonObject("ff").add("d", jsonBody.getAsJsonArray("splits"));
131+
targetBody.getAsJsonObject("ff").add("s", jsonBody.get("since"));
132+
targetBody.getAsJsonObject("ff").add("t", jsonBody.get("till"));
133+
return Json.toJson(targetBody);
83134
}
84135

85136
private URI buildURL(FetchOptions options, long since, long sinceRBS) throws URISyntaxException {

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,10 @@ public CustomHeaderDecorator customHeaderDecorator() {
412412
return _customHeaderDecorator;
413413
}
414414

415+
public boolean isRootURIOverriden() {
416+
return _endpoint == SDK_ENDPOINT;
417+
}
418+
415419
public CustomHttpModule alternativeHTTPModule() { return _alternativeHTTPModule; }
416420
public static final class Builder {
417421

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn
225225
RuleBasedSegmentParser ruleBasedSegmentParser = new RuleBasedSegmentParser();
226226
// SplitFetcher
227227
_splitFetcher = buildSplitFetcher(splitCache, splitParser, flagSetsFilter,
228-
ruleBasedSegmentParser, ruleBasedSegmentCache);
228+
ruleBasedSegmentParser, ruleBasedSegmentCache, config.isRootURIOverriden());
229229

230230
// SplitSynchronizationTask
231231
_splitSynchronizationTask = new SplitSynchronizationTask(_splitFetcher,
@@ -623,9 +623,9 @@ private SegmentSynchronizationTaskImp buildSegments(SplitClientConfig config,
623623

624624
private SplitFetcher buildSplitFetcher(SplitCacheProducer splitCacheProducer, SplitParser splitParser,
625625
FlagSetsFilter flagSetsFilter, RuleBasedSegmentParser ruleBasedSegmentParser,
626-
RuleBasedSegmentCacheProducer ruleBasedSegmentCache) throws URISyntaxException {
626+
RuleBasedSegmentCacheProducer ruleBasedSegmentCache, boolean isRootURIOverriden) throws URISyntaxException {
627627
SplitChangeFetcher splitChangeFetcher = HttpSplitChangeFetcher.create(_splitHttpClient, _rootTarget,
628-
_telemetryStorageProducer);
628+
_telemetryStorageProducer, isRootURIOverriden);
629629
return new SplitFetcherImp(splitChangeFetcher, splitParser, splitCacheProducer, _telemetryStorageProducer,
630630
flagSetsFilter, ruleBasedSegmentParser, ruleBasedSegmentCache);
631631
}

0 commit comments

Comments
 (0)