66import com .google .common .collect .Multiset ;
77import com .google .common .collect .Multisets ;
88import com .google .common .collect .Sets ;
9- import io .split .client .dtos .Condition ;
10- import io .split .client .dtos .Matcher ;
11- import io .split .client .dtos .MatcherType ;
129import io .split .client .dtos .Split ;
1310import io .split .client .dtos .SplitChange ;
1411import io .split .client .dtos .Status ;
1512import io .split .engine .SDKReadinessGates ;
13+ import io .split .engine .cache .SplitCache ;
1614import org .slf4j .Logger ;
1715import org .slf4j .LoggerFactory ;
1816
1917import java .util .Collection ;
2018import java .util .List ;
2119import java .util .Map ;
2220import java .util .Set ;
23- import java .util .concurrent .atomic .AtomicLong ;
2421
2522import static com .google .common .base .Preconditions .checkNotNull ;
2623
@@ -35,9 +32,9 @@ public class RefreshableSplitFetcher implements SplitFetcher, Runnable {
3532
3633 private final SplitParser _parser ;
3734 private final SplitChangeFetcher _splitChangeFetcher ;
38- private final AtomicLong _changeNumber ;
39-
40- private Map < String , ParsedSplit > _concurrentMap = Maps . newConcurrentMap ();
35+ private final SplitCache _splitCache ;
36+ private final SDKReadinessGates _gates ;
37+ private final Object _lock = new Object ();
4138
4239 /**
4340 * Contains all the traffic types that are currently being used by the splits and also the count
@@ -49,45 +46,22 @@ public class RefreshableSplitFetcher implements SplitFetcher, Runnable {
4946 * an ARCHIVED split is received, we know if we need to remove a traffic type from the multiset.
5047 */
5148 Multiset <String > _concurrentTrafficTypeNameSet = ConcurrentHashMultiset .create ();
52- private final SDKReadinessGates _gates ;
53-
54- private final Object _lock = new Object ();
5549
56-
57- public RefreshableSplitFetcher (SplitChangeFetcher splitChangeFetcher , SplitParser parser , SDKReadinessGates gates ) {
58- this (splitChangeFetcher , parser , gates , -1 );
59- }
60-
61- /**
62- * This constructor is package private because it is meant primarily for unit tests
63- * where we want to set the starting change number. All regular clients should use
64- * the public constructor.
65- *
66- * @param splitChangeFetcher MUST NOT be null
67- * @param parser MUST NOT be null
68- * @param startingChangeNumber
69- */
70- /*package private*/ RefreshableSplitFetcher (SplitChangeFetcher splitChangeFetcher ,
71- SplitParser parser ,
72- SDKReadinessGates gates ,
73- long startingChangeNumber ) {
74- _splitChangeFetcher = splitChangeFetcher ;
75- _parser = parser ;
76- _gates = gates ;
77- _changeNumber = new AtomicLong (startingChangeNumber );
78-
79- checkNotNull (_parser );
80- checkNotNull (_splitChangeFetcher );
50+ public RefreshableSplitFetcher (SplitChangeFetcher splitChangeFetcher , SplitParser parser , SDKReadinessGates gates , SplitCache splitCache ) {
51+ _splitChangeFetcher = checkNotNull (splitChangeFetcher );
52+ _parser = checkNotNull (parser );
53+ _gates = checkNotNull (gates );
54+ _splitCache = checkNotNull (splitCache );
8155 }
8256
8357 @ Override
8458 public void forceRefresh () {
8559 _log .debug ("Force Refresh splits starting ..." );
8660 try {
8761 while (true ) {
88- long start = _changeNumber . get ();
62+ long start = _splitCache . getChangeNumber ();
8963 runWithoutExceptionHandling ();
90- long end = _changeNumber . get ();
64+ long end = _splitCache . getChangeNumber ();
9165
9266 if (start >= end ) {
9367 break ;
@@ -103,13 +77,13 @@ public void forceRefresh() {
10377
10478 @ Override
10579 public long changeNumber () {
106- return _changeNumber . get ();
80+ return _splitCache . getChangeNumber ();
10781 }
10882
10983 @ Override
11084 public void killSplit (String splitName , String defaultTreatment , long changeNumber ) {
11185 synchronized (_lock ) {
112- ParsedSplit parsedSplit = _concurrentMap .get (splitName );
86+ ParsedSplit parsedSplit = _splitCache .get (splitName );
11387
11488 ParsedSplit updatedSplit = new ParsedSplit (parsedSplit .feature (),
11589 parsedSplit .seed (),
@@ -123,17 +97,17 @@ public void killSplit(String splitName, String defaultTreatment, long changeNumb
12397 parsedSplit .algo (),
12498 parsedSplit .configurations ());
12599
126- _concurrentMap .put (splitName , updatedSplit );
100+ _splitCache .put (updatedSplit );
127101 }
128102 }
129103
130104 @ Override
131105 public ParsedSplit fetch (String test ) {
132- return _concurrentMap .get (test );
106+ return _splitCache .get (test );
133107 }
134108
135109 public List <ParsedSplit > fetchAll () {
136- return Lists .newArrayList (_concurrentMap . values ());
110+ return Lists .newArrayList (_splitCache . getAll ());
137111 }
138112
139113 @ Override
@@ -145,18 +119,18 @@ public Set<String> fetchKnownTrafficTypes() {
145119 }
146120
147121 public Collection <ParsedSplit > fetch () {
148- return _concurrentMap . values ();
122+ return _splitCache . getAll ();
149123 }
150124
151125 public void clear () {
152- _concurrentMap .clear ();
126+ _splitCache .clear ();
153127 _concurrentTrafficTypeNameSet .clear ();
154128 }
155129
156130 @ Override
157131 public void run () {
158132 _log .debug ("Fetch splits starting ..." );
159- long start = _changeNumber . get ();
133+ long start = _splitCache . getChangeNumber ();
160134 try {
161135 runWithoutExceptionHandling ();
162136 _gates .splitsAreReady ();
@@ -170,38 +144,38 @@ public void run() {
170144 }
171145 } finally {
172146 if (_log .isDebugEnabled ()) {
173- _log .debug ("split fetch before: " + start + ", after: " + _changeNumber . get ());
147+ _log .debug ("split fetch before: " + start + ", after: " + _splitCache . getChangeNumber ());
174148 }
175149 }
176150 }
177151
178152 public void runWithoutExceptionHandling () throws InterruptedException {
179- SplitChange change = _splitChangeFetcher .fetch (_changeNumber . get ());
153+ SplitChange change = _splitChangeFetcher .fetch (_splitCache . getChangeNumber ());
180154
181155 if (change == null ) {
182156 throw new IllegalStateException ("SplitChange was null" );
183157 }
184158
185- if (change .till == _changeNumber . get ()) {
159+ if (change .till == _splitCache . getChangeNumber ()) {
186160 // no change.
187161 return ;
188162 }
189163
190- if (change .since != _changeNumber . get () || change .till < _changeNumber . get ()) {
164+ if (change .since != _splitCache . getChangeNumber () || change .till < _splitCache . getChangeNumber ()) {
191165 // some other thread may have updated the shared state. exit
192166 return ;
193167 }
194168
195169 if (change .splits .isEmpty ()) {
196170 // there are no changes. weird!
197- _changeNumber . set (change .till );
171+ _splitCache . setChangeNumber (change .till );
198172 return ;
199173 }
200174
201175 synchronized (_lock ) {
202176 // check state one more time.
203- if (change .since != _changeNumber . get ()
204- || change .till < _changeNumber . get ()) {
177+ if (change .since != _splitCache . getChangeNumber ()
178+ || change .till < _splitCache . getChangeNumber ()) {
205179 // some other thread may have updated the shared state. exit
206180 return ;
207181 }
@@ -243,7 +217,7 @@ public void runWithoutExceptionHandling() throws InterruptedException {
243217 // If it's deleted & recreated, the old one should be decreased and the new one increased.
244218 // To handle both cases, we simply delete the old one if the split is present.
245219 // The new one is always increased.
246- ParsedSplit current = _concurrentMap .get (split .name );
220+ ParsedSplit current = _splitCache .get (split .name );
247221 if (current != null && current .trafficTypeName () != null ) {
248222 trafficTypeNamesToRemove .add (current .trafficTypeName ());
249223 }
@@ -253,13 +227,13 @@ public void runWithoutExceptionHandling() throws InterruptedException {
253227 }
254228 }
255229
256- _concurrentMap .putAll (toAdd );
230+ _splitCache .putAll (toAdd );
257231 _concurrentTrafficTypeNameSet .addAll (trafficTypeNamesToAdd );
258232 //removeAll does not work here, since it wont remove all the occurrences, just one
259233 Multisets .removeOccurrences (_concurrentTrafficTypeNameSet , trafficTypeNamesToRemove );
260234
261235 for (String remove : toRemove ) {
262- _concurrentMap .remove (remove );
236+ _splitCache .remove (remove );
263237 }
264238
265239 if (!toAdd .isEmpty ()) {
@@ -270,7 +244,7 @@ public void runWithoutExceptionHandling() throws InterruptedException {
270244 _log .debug ("Deleted features: " + toRemove );
271245 }
272246
273- _changeNumber . set (change .till );
247+ _splitCache . setChangeNumber (change .till );
274248 }
275249 }
276250}
0 commit comments