@@ -46,26 +46,27 @@ public class SplitsSyncHelper {
4646 private final RuleBasedSegmentStorageProducer mRuleBasedSegmentStorage ;
4747 private final TelemetryRuntimeProducer mTelemetryRuntimeProducer ;
4848 private final BackoffCounter mBackoffCounter ;
49- private final String mFlagsSpec ;
49+ private final OutdatedSplitProxyHandler mOutdatedSplitProxyHandler ;
5050
5151 public SplitsSyncHelper (@ NonNull HttpFetcher <TargetingRulesChange > splitFetcher ,
5252 @ NonNull SplitsStorage splitsStorage ,
5353 @ NonNull SplitChangeProcessor splitChangeProcessor ,
5454 @ NonNull RuleBasedSegmentChangeProcessor ruleBasedSegmentChangeProcessor ,
5555 @ NonNull RuleBasedSegmentStorageProducer ruleBasedSegmentStorage ,
5656 @ NonNull TelemetryRuntimeProducer telemetryRuntimeProducer ,
57- @ Nullable String flagsSpec ) {
57+ @ Nullable String flagsSpec ,
58+ boolean forBackgroundSync ) {
5859 this (splitFetcher ,
5960 splitsStorage ,
6061 splitChangeProcessor ,
6162 ruleBasedSegmentChangeProcessor ,
6263 ruleBasedSegmentStorage ,
6364 telemetryRuntimeProducer ,
6465 new ReconnectBackoffCounter (1 , ON_DEMAND_FETCH_BACKOFF_MAX_WAIT ),
65- flagsSpec );
66+ flagsSpec ,
67+ forBackgroundSync );
6668 }
6769
68- @ VisibleForTesting
6970 public SplitsSyncHelper (@ NonNull HttpFetcher <TargetingRulesChange > splitFetcher ,
7071 @ NonNull SplitsStorage splitsStorage ,
7172 @ NonNull SplitChangeProcessor splitChangeProcessor ,
@@ -74,14 +75,36 @@ public SplitsSyncHelper(@NonNull HttpFetcher<TargetingRulesChange> splitFetcher,
7475 @ NonNull TelemetryRuntimeProducer telemetryRuntimeProducer ,
7576 @ NonNull BackoffCounter backoffCounter ,
7677 @ Nullable String flagsSpec ) {
78+ this (splitFetcher ,
79+ splitsStorage ,
80+ splitChangeProcessor ,
81+ ruleBasedSegmentChangeProcessor ,
82+ ruleBasedSegmentStorage ,
83+ telemetryRuntimeProducer ,
84+ backoffCounter ,
85+ flagsSpec ,
86+ false );
87+ }
88+
89+ @ VisibleForTesting
90+ public SplitsSyncHelper (@ NonNull HttpFetcher <TargetingRulesChange > splitFetcher ,
91+ @ NonNull SplitsStorage splitsStorage ,
92+ @ NonNull SplitChangeProcessor splitChangeProcessor ,
93+ @ NonNull RuleBasedSegmentChangeProcessor ruleBasedSegmentChangeProcessor ,
94+ @ NonNull RuleBasedSegmentStorageProducer ruleBasedSegmentStorage ,
95+ @ NonNull TelemetryRuntimeProducer telemetryRuntimeProducer ,
96+ @ NonNull BackoffCounter backoffCounter ,
97+ @ Nullable String flagsSpec ,
98+ boolean forBackgroundSync ) {
7799 mSplitFetcher = checkNotNull (splitFetcher );
78100 mSplitsStorage = checkNotNull (splitsStorage );
79101 mSplitChangeProcessor = checkNotNull (splitChangeProcessor );
80102 mRuleBasedSegmentChangeProcessor = checkNotNull (ruleBasedSegmentChangeProcessor );
81103 mRuleBasedSegmentStorage = checkNotNull (ruleBasedSegmentStorage );
82104 mTelemetryRuntimeProducer = checkNotNull (telemetryRuntimeProducer );
83105 mBackoffCounter = checkNotNull (backoffCounter );
84- mFlagsSpec = flagsSpec ;
106+ String mPreviousSpec = "1.2" ;
107+ mOutdatedSplitProxyHandler = new OutdatedSplitProxyHandler (flagsSpec , mPreviousSpec , forBackgroundSync );
85108 }
86109
87110 public SplitTaskExecutionInfo sync (SinceChangeNumbers till , int onDemandFetchBackoffMaxRetries ) {
@@ -113,6 +136,14 @@ private SplitTaskExecutionInfo sync(SinceChangeNumbers till, boolean clearBefore
113136 Collections .singletonMap (SplitTaskExecutionInfo .DO_NOT_RETRY , true ));
114137 }
115138
139+ if (HttpStatus .isProxyOutdated (httpStatus )) {
140+ try {
141+ return handleOutdatedProxy (till , avoidCache , resetChangeNumber , onDemandFetchBackoffMaxRetries );
142+ } catch (Exception e1 ) {
143+ logError ("Unexpected while handling outdated proxy" + e1 .getLocalizedMessage ());
144+ }
145+ }
146+
116147 return SplitTaskExecutionInfo .error (SplitTaskType .SPLITS_SYNC );
117148 } catch (Exception e ) {
118149 logError ("Unexpected while fetching feature flags" + e .getLocalizedMessage ());
@@ -123,6 +154,25 @@ private SplitTaskExecutionInfo sync(SinceChangeNumbers till, boolean clearBefore
123154 return SplitTaskExecutionInfo .success (SplitTaskType .SPLITS_SYNC );
124155 }
125156
157+ private SplitTaskExecutionInfo handleOutdatedProxy (SinceChangeNumbers till , boolean avoidCache , boolean resetChangeNumber , int onDemandFetchBackoffMaxRetries ) throws Exception {
158+ OutdatedSplitProxyHandler .ProxyHandlingType handle = mOutdatedSplitProxyHandler .handle ();
159+ switch (handle ) {
160+ case FALLBACK : {
161+ long flagsSince = till .getFlagsSince ();
162+ SinceChangeNumbers newTill = new SinceChangeNumbers (flagsSince , null );
163+ attemptSplitSync (newTill , false , false , CdnByPassType .NONE , false , onDemandFetchBackoffMaxRetries );
164+ break ;
165+ }
166+ case RECOVERY : {
167+ SinceChangeNumbers newTill = new SinceChangeNumbers (-1 , -1L );
168+ attemptSplitSync (newTill , true , false , CdnByPassType .NONE , true , onDemandFetchBackoffMaxRetries );
169+ break ;
170+ }
171+ }
172+
173+ return SplitTaskExecutionInfo .success (SplitTaskType .SPLITS_SYNC );
174+ }
175+
126176 /**
127177 * @param targetChangeNumber target changeNumber
128178 * @param clearBeforeUpdate whether to clear splits storage before updating it
@@ -140,7 +190,8 @@ private CdnByPassType attemptSplitSync(SinceChangeNumbers targetChangeNumber, bo
140190 SinceChangeNumbers retrievedChangeNumber = fetchUntil (targetChangeNumber , clearBeforeUpdate , avoidCache , withCdnBypass , resetChangeNumber );
141191 resetChangeNumber = false ;
142192
143- if (targetChangeNumber .getFlagsSince () <= retrievedChangeNumber .getFlagsSince () && targetChangeNumber .getRbsSince () <= retrievedChangeNumber .getRbsSince ()) {
193+ if (targetChangeNumber .getFlagsSince () <= retrievedChangeNumber .getFlagsSince () &&
194+ targetChangeNumber .getRbsSince () != null && retrievedChangeNumber .getRbsSince () != null && targetChangeNumber .getRbsSince () <= retrievedChangeNumber .getRbsSince ()) {
144195 return CdnByPassType .NONE ;
145196 }
146197
@@ -170,7 +221,7 @@ private SinceChangeNumbers fetchUntil(SinceChangeNumbers till, boolean clearBefo
170221 long changeNumber = (resetChangeNumber ) ? -1 : mSplitsStorage .getTill ();
171222 long rbsChangeNumber = (resetChangeNumber ) ? -1 : mRuleBasedSegmentStorage .getChangeNumber ();
172223 resetChangeNumber = false ;
173- if (newTill .getFlagsSince () < changeNumber && newTill .getRbsSince () < rbsChangeNumber ) {
224+ if (( newTill .getFlagsSince () < changeNumber ) && (( newTill .getRbsSince () == null ) || ( newTill . getRbsSince () < rbsChangeNumber )) ) {
174225 return new SinceChangeNumbers (changeNumber , rbsChangeNumber );
175226 }
176227
@@ -189,11 +240,14 @@ private SinceChangeNumbers fetchUntil(SinceChangeNumbers till, boolean clearBefo
189240
190241 private TargetingRulesChange fetchSplits (SinceChangeNumbers till , boolean avoidCache , CdnByPassType cdnByPassType ) throws HttpFetcherException {
191242 Map <String , Object > params = new LinkedHashMap <>();
192- if (mFlagsSpec != null && !mFlagsSpec .trim ().isEmpty ()) {
193- params .put (FLAGS_SPEC_PARAM , mFlagsSpec );
243+ String flagsSpec = mOutdatedSplitProxyHandler .getCurrentSpec ();
244+ if (flagsSpec != null && !flagsSpec .trim ().isEmpty ()) {
245+ params .put (FLAGS_SPEC_PARAM , flagsSpec );
194246 }
195247 params .put (SINCE_PARAM , till .getFlagsSince ());
196- params .put (RBS_SINCE_PARAM , till .getRbsSince ());
248+ if (till .getRbsSince () != null ) {
249+ params .put (RBS_SINCE_PARAM , till .getRbsSince ());
250+ }
197251
198252 if (cdnByPassType == CdnByPassType .RBS ) {
199253 params .put (TILL_PARAM , till .getRbsSince ());
@@ -231,9 +285,10 @@ private void logError(String message) {
231285
232286 public static class SinceChangeNumbers {
233287 private final long mFlagsSince ;
234- private final long mRbsSince ;
288+ @ Nullable
289+ private final Long mRbsSince ;
235290
236- public SinceChangeNumbers (long flagsSince , long rbsSince ) {
291+ public SinceChangeNumbers (long flagsSince , @ Nullable Long rbsSince ) {
237292 mFlagsSince = flagsSince ;
238293 mRbsSince = rbsSince ;
239294 }
@@ -242,15 +297,16 @@ public long getFlagsSince() {
242297 return mFlagsSince ;
243298 }
244299
245- public long getRbsSince () {
300+ @ Nullable
301+ public Long getRbsSince () {
246302 return mRbsSince ;
247303 }
248304
249305 @ Override
250306 public boolean equals (@ Nullable Object obj ) {
251307 return obj instanceof SinceChangeNumbers &&
252308 mFlagsSince == ((SinceChangeNumbers ) obj ).mFlagsSince &&
253- mRbsSince == ((SinceChangeNumbers ) obj ).mRbsSince ;
309+ ( mRbsSince == null && ((SinceChangeNumbers ) obj ).mRbsSince == null ) ;
254310 }
255311
256312 @ NonNull
0 commit comments