1313import java .util .concurrent .ExecutorService ;
1414import java .util .concurrent .Executors ;
1515import java .util .concurrent .TimeUnit ;
16- import java .util .concurrent .atomic .AtomicReference ;
17- import java .util .concurrent .locks .ReentrantLock ;
1816
1917import io .split .android .client .dtos .RuleBasedSegmentChange ;
2018import io .split .android .client .dtos .SplitChange ;
@@ -54,8 +52,7 @@ public class SplitsSyncHelper {
5452 private final BackoffCounter mBackoffCounter ;
5553 private final OutdatedSplitProxyHandler mOutdatedSplitProxyHandler ;
5654 private final ExecutorService mExecutor ;
57- private final AtomicReference <TargetingRulesChange > mCacheRef ;
58- private ReentrantLock mCachedFetchLock ;
55+ private final TargetingRulesCache mTargetingRulesCache ;
5956
6057 public SplitsSyncHelper (@ NonNull HttpFetcher <TargetingRulesChange > splitFetcher ,
6158 @ NonNull SplitsStorage splitsStorage ,
@@ -66,8 +63,7 @@ public SplitsSyncHelper(@NonNull HttpFetcher<TargetingRulesChange> splitFetcher,
6663 @ NonNull TelemetryRuntimeProducer telemetryRuntimeProducer ,
6764 @ Nullable String flagsSpec ,
6865 boolean forBackgroundSync ,
69- @ Nullable AtomicReference <TargetingRulesChange > cacheRef ,
70- @ Nullable ReentrantLock cachedFetchLock ) {
66+ @ Nullable TargetingRulesCache targetingRulesCache ) {
7167 this (splitFetcher ,
7268 splitsStorage ,
7369 splitChangeProcessor ,
@@ -79,8 +75,7 @@ public SplitsSyncHelper(@NonNull HttpFetcher<TargetingRulesChange> splitFetcher,
7975 flagsSpec ,
8076 forBackgroundSync ,
8177 DEFAULT_PROXY_CHECK_INTERVAL_MILLIS ,
82- cacheRef ,
83- cachedFetchLock );
78+ targetingRulesCache );
8479 }
8580
8681 public SplitsSyncHelper (@ NonNull HttpFetcher <TargetingRulesChange > splitFetcher ,
@@ -92,8 +87,7 @@ public SplitsSyncHelper(@NonNull HttpFetcher<TargetingRulesChange> splitFetcher,
9287 @ NonNull TelemetryRuntimeProducer telemetryRuntimeProducer ,
9388 @ NonNull BackoffCounter backoffCounter ,
9489 @ Nullable String flagsSpec ,
95- @ Nullable AtomicReference <TargetingRulesChange > cacheRef ,
96- @ Nullable ReentrantLock cachedFetchLock ) {
90+ @ Nullable TargetingRulesCache targetingRulesCache ) {
9791 this (splitFetcher ,
9892 splitsStorage ,
9993 splitChangeProcessor ,
@@ -105,8 +99,7 @@ public SplitsSyncHelper(@NonNull HttpFetcher<TargetingRulesChange> splitFetcher,
10599 flagsSpec ,
106100 false ,
107101 DEFAULT_PROXY_CHECK_INTERVAL_MILLIS ,
108- cacheRef ,
109- cachedFetchLock );
102+ targetingRulesCache );
110103 }
111104
112105 @ VisibleForTesting
@@ -121,8 +114,7 @@ public SplitsSyncHelper(@NonNull HttpFetcher<TargetingRulesChange> splitFetcher,
121114 @ Nullable String flagsSpec ,
122115 boolean forBackgroundSync ,
123116 long proxyCheckIntervalMillis ,
124- @ Nullable AtomicReference <TargetingRulesChange > cacheRef ,
125- @ Nullable ReentrantLock cachedFetchLock ) {
117+ @ Nullable TargetingRulesCache targetingRulesCache ) {
126118 mSplitFetcher = checkNotNull (splitFetcher );
127119 mSplitsStorage = checkNotNull (splitsStorage );
128120 mSplitChangeProcessor = checkNotNull (splitChangeProcessor );
@@ -132,8 +124,7 @@ public SplitsSyncHelper(@NonNull HttpFetcher<TargetingRulesChange> splitFetcher,
132124 mBackoffCounter = checkNotNull (backoffCounter );
133125 mOutdatedSplitProxyHandler = new OutdatedSplitProxyHandler (flagsSpec , forBackgroundSync , generalInfoStorage , proxyCheckIntervalMillis );
134126 mExecutor = Executors .newSingleThreadExecutor ();
135- mCacheRef = cacheRef ;
136- mCachedFetchLock = cachedFetchLock ;
127+ mTargetingRulesCache = targetingRulesCache ;
137128 }
138129
139130 public SplitTaskExecutionInfo sync (SinceChangeNumbers till , int onDemandFetchBackoffMaxRetries ) {
@@ -236,52 +227,39 @@ private CdnByPassType attemptSplitSync(SinceChangeNumbers targetChangeNumber, bo
236227
237228 private SinceChangeNumbers fetchUntil (SinceChangeNumbers till , boolean clearBeforeUpdate , boolean avoidCache , CdnByPassType withCdnByPass , boolean resetChangeNumber ) throws Exception {
238229 boolean shouldClearBeforeUpdate = clearBeforeUpdate ;
239- boolean usedCache = false ;
240230
241231 SinceChangeNumbers newTill = till ;
242- boolean lockAcquired = false ;
243- try {
244- while (true ) {
245- if (mCachedFetchLock != null && !lockAcquired ) {
246- mCachedFetchLock .lock ();
247- lockAcquired = true ;
248- }
249- long changeNumber = (resetChangeNumber ) ? -1 : mSplitsStorage .getTill ();
250- long rbsChangeNumber = (resetChangeNumber ) ? -1 : mRuleBasedSegmentStorage .getChangeNumber ();
251- resetChangeNumber = false ;
252- if ((newTill .getFlagsSince () < changeNumber ) && ((newTill .getRbsSince () == null ) || (newTill .getRbsSince () < rbsChangeNumber ))) {
253- return new SinceChangeNumbers (changeNumber , rbsChangeNumber );
254- }
232+ while (true ) {
233+ long changeNumber = (resetChangeNumber ) ? -1 : mSplitsStorage .getTill ();
234+ long rbsChangeNumber = (resetChangeNumber ) ? -1 : mRuleBasedSegmentStorage .getChangeNumber ();
235+ resetChangeNumber = false ;
236+ if ((newTill .getFlagsSince () < changeNumber ) && ((newTill .getRbsSince () == null ) || (newTill .getRbsSince () < rbsChangeNumber ))) {
237+ return new SinceChangeNumbers (changeNumber , rbsChangeNumber );
238+ }
255239
256- TargetingRulesChange targetingRulesChange ;
257- if ((rbsChangeNumber == -1L ) && changeNumber == -1 && mCacheRef != null && mCacheRef .get () != null ) {
240+ TargetingRulesChange targetingRulesChange ;
241+ // Try to use cached value for fresh installs
242+ if ((rbsChangeNumber == -1L ) && changeNumber == -1 && mTargetingRulesCache != null ) {
243+ targetingRulesChange = mTargetingRulesCache .getAndConsume ();
244+ if (targetingRulesChange != null ) {
258245 Logger .d ("Fresh install: Using prefetched targeting rules from cache" );
259- targetingRulesChange = mCacheRef .get ();
260- usedCache = true ;
261246 } else {
262247 Logger .d ("Fetching targeting rules - changeNumber: " + changeNumber + ", rbsChangeNumber: " + rbsChangeNumber );
263248 targetingRulesChange = fetchSplits (new SinceChangeNumbers (changeNumber , rbsChangeNumber ), avoidCache , withCdnByPass );
264249 }
250+ } else {
251+ Logger .d ("Fetching targeting rules - changeNumber: " + changeNumber + ", rbsChangeNumber: " + rbsChangeNumber );
252+ targetingRulesChange = fetchSplits (new SinceChangeNumbers (changeNumber , rbsChangeNumber ), avoidCache , withCdnByPass );
253+ }
265254
266- // Release lock after first use of cache to avoid blocking subsequent syncs
267- if (lockAcquired && usedCache ) {
268- mCachedFetchLock .unlock ();
269- lockAcquired = false ;
270- }
271-
272- SplitChange splitChange = targetingRulesChange .getFeatureFlagsChange ();
273- RuleBasedSegmentChange ruleBasedSegmentChange = targetingRulesChange .getRuleBasedSegmentsChange ();
274- updateStorage (shouldClearBeforeUpdate , splitChange , ruleBasedSegmentChange );
275- shouldClearBeforeUpdate = false ;
255+ SplitChange splitChange = targetingRulesChange .getFeatureFlagsChange ();
256+ RuleBasedSegmentChange ruleBasedSegmentChange = targetingRulesChange .getRuleBasedSegmentsChange ();
257+ updateStorage (shouldClearBeforeUpdate , splitChange , ruleBasedSegmentChange );
258+ shouldClearBeforeUpdate = false ;
276259
277- newTill = new SinceChangeNumbers (splitChange .till , ruleBasedSegmentChange .getTill ());
278- if (splitChange .till == splitChange .since && ruleBasedSegmentChange .getTill () == ruleBasedSegmentChange .getSince ()) {
279- return new SinceChangeNumbers (splitChange .till , ruleBasedSegmentChange .getTill ());
280- }
281- }
282- } finally {
283- if (lockAcquired ) {
284- mCachedFetchLock .unlock ();
260+ newTill = new SinceChangeNumbers (splitChange .till , ruleBasedSegmentChange .getTill ());
261+ if (splitChange .till == splitChange .since && ruleBasedSegmentChange .getTill () == ruleBasedSegmentChange .getSince ()) {
262+ return new SinceChangeNumbers (splitChange .till , ruleBasedSegmentChange .getTill ());
285263 }
286264 }
287265 }
@@ -310,9 +288,8 @@ public static void fetchSplits(SinceChangeNumbers till,
310288 boolean avoidCache ,
311289 String currentSpec ,
312290 HttpFetcher <TargetingRulesChange > fetcher ,
313- @ NonNull AtomicReference <TargetingRulesChange > cacheRef ,
314- @ NonNull ReentrantLock mCachedFetchLock ) throws HttpFetcherException {
315- mCachedFetchLock .lock ();
291+ @ NonNull TargetingRulesCache cache ) throws HttpFetcherException {
292+ cache .lock ();
316293 try {
317294 Map <String , Object > params = new LinkedHashMap <>();
318295 if (currentSpec != null && !currentSpec .trim ().isEmpty ()) {
@@ -321,10 +298,10 @@ public static void fetchSplits(SinceChangeNumbers till,
321298 params .put (SINCE_PARAM , till .getFlagsSince ());
322299 params .put (RBS_SINCE_PARAM , till .getRbsSince ());
323300
324- TargetingRulesChange execute = fetcher .execute (params , getHeaders (avoidCache ));
325- cacheRef .set (execute );
301+ TargetingRulesChange result = fetcher .execute (params , getHeaders (avoidCache ));
302+ cache .set (result );
326303 } finally {
327- mCachedFetchLock .unlock ();
304+ cache .unlock ();
328305 }
329306 }
330307
0 commit comments