22
33import com .google .common .annotations .VisibleForTesting ;
44
5+ import io .split .Spec ;
56import io .split .client .dtos .SplitChange ;
67import io .split .client .dtos .SplitHttpResponse ;
8+ import io .split .client .dtos .SplitChangesOldPayloadDto ;
79import io .split .client .exceptions .UriTooLongException ;
810import io .split .client .utils .Json ;
911import io .split .client .utils .Utils ;
2224import java .net .URISyntaxException ;
2325
2426import static com .google .common .base .Preconditions .checkNotNull ;
25- import static io .split .Spec .SPEC_VERSION ;
27+ import static io .split .Spec .SPEC_1_3 ;
28+ import static io .split .Spec .SPEC_1_1 ;
2629
2730/**
2831 * Created by adilaijaz on 5/30/15.
@@ -31,23 +34,30 @@ public final class HttpSplitChangeFetcher implements SplitChangeFetcher {
3134 private static final Logger _log = LoggerFactory .getLogger (HttpSplitChangeFetcher .class );
3235
3336 private static final String SINCE = "since" ;
37+ private static final String RB_SINCE = "rbSince" ;
3438 private static final String TILL = "till" ;
3539 private static final String SETS = "sets" ;
3640 private static final String SPEC = "s" ;
41+ private String specVersion = SPEC_1_3 ;
42+ private int PROXY_CHECK_INTERVAL_MILLISECONDS_SS = 24 * 60 * 60 * 1000 ;
43+ private Long _lastProxyCheckTimestamp = 0L ;
3744 private final SplitHttpClient _client ;
3845 private final URI _target ;
3946 private final TelemetryRuntimeProducer _telemetryRuntimeProducer ;
47+ private final boolean _rootURIOverriden ;
4048
41- public static HttpSplitChangeFetcher create (SplitHttpClient client , URI root , TelemetryRuntimeProducer telemetryRuntimeProducer )
49+ public static HttpSplitChangeFetcher create (SplitHttpClient client , URI root , TelemetryRuntimeProducer telemetryRuntimeProducer ,
50+ boolean rootURIOverriden )
4251 throws URISyntaxException {
43- return new HttpSplitChangeFetcher (client , Utils .appendPath (root , "api/splitChanges" ), telemetryRuntimeProducer );
52+ return new HttpSplitChangeFetcher (client , Utils .appendPath (root , "api/splitChanges" ), telemetryRuntimeProducer , rootURIOverriden );
4453 }
4554
46- private HttpSplitChangeFetcher (SplitHttpClient client , URI uri , TelemetryRuntimeProducer telemetryRuntimeProducer ) {
55+ private HttpSplitChangeFetcher (SplitHttpClient client , URI uri , TelemetryRuntimeProducer telemetryRuntimeProducer , boolean rootURIOverriden ) {
4756 _client = client ;
4857 _target = uri ;
4958 checkNotNull (_target );
5059 _telemetryRuntimeProducer = checkNotNull (telemetryRuntimeProducer );
60+ _rootURIOverriden = rootURIOverriden ;
5161 }
5262
5363 long makeRandomTill () {
@@ -56,38 +66,66 @@ long makeRandomTill() {
5666 }
5767
5868 @ Override
59- public SplitChange fetch (long since , FetchOptions options ) {
60-
69+ public SplitChange fetch (long since , long sinceRBS , FetchOptions options ) {
6170 long start = System .currentTimeMillis ();
62-
6371 try {
64- URIBuilder uriBuilder = new URIBuilder (_target ).addParameter (SPEC , "" + SPEC_VERSION );
65- uriBuilder .addParameter (SINCE , "" + since );
66- if (!options .flagSetsFilter ().isEmpty ()) {
67- uriBuilder .addParameter (SETS , "" + options .flagSetsFilter ());
68- }
69- if (options .hasCustomCN ()) {
70- uriBuilder .addParameter (TILL , "" + options .targetCN ());
72+ URI uri = buildURL (options , since , sinceRBS );
73+ if (specVersion .equals (SPEC_1_1 ) && (System .currentTimeMillis () - _lastProxyCheckTimestamp >= PROXY_CHECK_INTERVAL_MILLISECONDS_SS )) {
74+ _log .info ("Switching to new Feature flag spec ({}) and fetching." , SPEC_1_3 );
75+ specVersion = SPEC_1_3 ;
76+ uri = buildURL (options , -1 ,-1 );
7177 }
72- URI uri = uriBuilder .build ();
73- SplitHttpResponse response = _client .get (uri , options , null );
7478
79+ SplitHttpResponse response = _client .get (uri , options , null );
7580 if (response .statusCode () < HttpStatus .SC_OK || response .statusCode () >= HttpStatus .SC_MULTIPLE_CHOICES ) {
7681 if (response .statusCode () == HttpStatus .SC_REQUEST_URI_TOO_LONG ) {
7782 _log .error ("The amount of flag sets provided are big causing uri length error." );
7883 throw new UriTooLongException (String .format ("Status code: %s. Message: %s" , response .statusCode (), response .statusMessage ()));
7984 }
85+
86+ if (response .statusCode () == HttpStatus .SC_BAD_REQUEST && specVersion .equals (Spec .SPEC_1_3 ) && _rootURIOverriden ) {
87+ specVersion = Spec .SPEC_1_1 ;
88+ _log .warn ("Detected proxy without support for Feature flags spec {} version, will switch to spec version {}" ,
89+ SPEC_1_3 , SPEC_1_1 );
90+ _lastProxyCheckTimestamp = System .currentTimeMillis ();
91+ return fetch (since , sinceRBS , options );
92+ }
93+
8094 _telemetryRuntimeProducer .recordSyncError (ResourceEnum .SPLIT_SYNC , response .statusCode ());
8195 throw new IllegalStateException (
8296 String .format ("Could not retrieve splitChanges since %s; http return code %s" , since , response .statusCode ())
8397 );
8498 }
85- return Json .fromJson (response .body (), SplitChange .class );
99+
100+ if (specVersion .equals (Spec .SPEC_1_1 )) {
101+ return Json .fromJson (response .body (), SplitChangesOldPayloadDto .class ).toSplitChange ();
102+ }
103+
104+ SplitChange splitChange = Json .fromJson (response .body (), SplitChange .class );
105+ splitChange .clearCache = _lastProxyCheckTimestamp != 0 ;
106+ _lastProxyCheckTimestamp = 0L ;
107+ return splitChange ;
86108 } catch (Exception e ) {
87109 throw new IllegalStateException (String .format ("Problem fetching splitChanges since %s: %s" , since , e ), e );
88110 } finally {
89- _telemetryRuntimeProducer .recordSyncLatency (HTTPLatenciesEnum .SPLITS , System .currentTimeMillis ()-start );
111+ _telemetryRuntimeProducer .recordSyncLatency (HTTPLatenciesEnum .SPLITS , System .currentTimeMillis () - start );
112+ }
113+ }
114+
115+
116+ private URI buildURL (FetchOptions options , long since , long sinceRBS ) throws URISyntaxException {
117+ URIBuilder uriBuilder = new URIBuilder (_target ).addParameter (SPEC , "" + specVersion );
118+ uriBuilder .addParameter (SINCE , "" + since );
119+ if (specVersion .equals (SPEC_1_3 )) {
120+ uriBuilder .addParameter (RB_SINCE , "" + sinceRBS );
121+ }
122+ if (!options .flagSetsFilter ().isEmpty ()) {
123+ uriBuilder .addParameter (SETS , "" + options .flagSetsFilter ());
124+ }
125+ if (options .hasCustomCN ()) {
126+ uriBuilder .addParameter (TILL , "" + options .targetCN ());
90127 }
128+ return uriBuilder .build ();
91129 }
92130
93131 @ VisibleForTesting
0 commit comments