Skip to content

Commit f3d0ddb

Browse files
authored
Merge pull request #175 from splitio/split-fetcher-refactor-storage
Splits fetcher: Decouple storage
2 parents 4f104b9 + 1c45e77 commit f3d0ddb

File tree

9 files changed

+307
-284
lines changed

9 files changed

+307
-284
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ private boolean track(Event event) {
192192
event.trafficTypeName = event.trafficTypeName.toLowerCase();
193193
}
194194

195-
if (!_splitFetcher.fetchKnownTrafficTypes().contains(event.trafficTypeName)) {
195+
if (!_splitFetcher.trafficTypeExists(event.trafficTypeName)) {
196196
_log.warn("track: Traffic Type " + event.trafficTypeName + " does not have any corresponding Splits in this environment, " +
197197
"make sure you’re tracking your events to a valid traffic type defined in the Split console.");
198198
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
import io.split.client.metrics.CachedMetrics;
1212
import io.split.client.metrics.FireAndForgetMetrics;
1313
import io.split.client.metrics.HttpMetrics;
14+
import io.split.engine.cache.InMemoryCacheImp;
15+
import io.split.engine.cache.SplitCache;
1416
import io.split.engine.evaluator.Evaluator;
1517
import io.split.engine.evaluator.EvaluatorImp;
1618
import io.split.engine.SDKReadinessGates;
@@ -200,7 +202,8 @@ public SplitFactoryImpl(String apiToken, SplitClientConfig config) throws URISyn
200202
// Feature Changes
201203
SplitChangeFetcher splitChangeFetcher = HttpSplitChangeFetcher.create(httpclient, rootTarget, uncachedFireAndForget);
202204

203-
final RefreshableSplitFetcherProvider splitFetcherProvider = new RefreshableSplitFetcherProvider(splitChangeFetcher, splitParser, findPollingPeriod(RANDOM, config.featuresRefreshRate()), gates);
205+
final SplitCache cache = new InMemoryCacheImp();
206+
final RefreshableSplitFetcherProvider splitFetcherProvider = new RefreshableSplitFetcherProvider(splitChangeFetcher, splitParser, findPollingPeriod(RANDOM, config.featuresRefreshRate()), gates, cache);
204207

205208

206209
List<ImpressionListener> impressionListeners = new ArrayList<>();
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package io.split.engine.cache;
2+
3+
import com.google.common.collect.ConcurrentHashMultiset;
4+
import com.google.common.collect.Maps;
5+
import com.google.common.collect.Multiset;
6+
import com.google.common.collect.Sets;
7+
import io.split.engine.experiments.ParsedSplit;
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
10+
11+
import java.util.ArrayList;
12+
import java.util.Collection;
13+
import java.util.List;
14+
import java.util.Set;
15+
import java.util.concurrent.ConcurrentMap;
16+
import java.util.concurrent.atomic.AtomicLong;
17+
18+
public class InMemoryCacheImp implements SplitCache {
19+
20+
private static final Logger _log = LoggerFactory.getLogger(InMemoryCacheImp.class);
21+
22+
private final ConcurrentMap<String, ParsedSplit> _concurrentMap;
23+
private final Multiset<String> _concurrentTrafficTypeNameSet;
24+
25+
private AtomicLong _changeNumber;
26+
27+
public InMemoryCacheImp() {
28+
this(-1);
29+
}
30+
31+
public InMemoryCacheImp(long startingChangeNumber) {
32+
_concurrentMap = Maps.newConcurrentMap();
33+
_changeNumber = new AtomicLong(startingChangeNumber);
34+
_concurrentTrafficTypeNameSet = ConcurrentHashMultiset.create();
35+
}
36+
37+
@Override
38+
public void put(ParsedSplit split) {
39+
_concurrentMap.put(split.feature(), split);
40+
41+
if (split.trafficTypeName() != null) {
42+
_concurrentTrafficTypeNameSet.add(split.trafficTypeName());
43+
}
44+
}
45+
46+
@Override
47+
public boolean remove(String name) {
48+
ParsedSplit removed = _concurrentMap.remove(name);
49+
50+
if (removed != null && removed.trafficTypeName() != null) {
51+
_concurrentTrafficTypeNameSet.remove(removed.trafficTypeName());
52+
}
53+
54+
return removed != null;
55+
}
56+
57+
@Override
58+
public ParsedSplit get(String name) {
59+
return _concurrentMap.get(name);
60+
}
61+
62+
@Override
63+
public Collection<ParsedSplit> getAll() {
64+
return _concurrentMap.values();
65+
}
66+
67+
@Override
68+
public Collection<ParsedSplit> getMany(List<String> names) {
69+
List<ParsedSplit> splits = new ArrayList<>();
70+
71+
for (String name : names) {
72+
ParsedSplit split = _concurrentMap.get(name);
73+
74+
if (split != null) {
75+
splits.add(split);
76+
}
77+
}
78+
79+
return splits;
80+
}
81+
82+
@Override
83+
public long getChangeNumber() {
84+
return _changeNumber.get();
85+
}
86+
87+
@Override
88+
public void setChangeNumber(long changeNumber) {
89+
if (changeNumber < _changeNumber.get()) {
90+
_log.error("ChangeNumber for splits cache is less than previous");
91+
}
92+
93+
_changeNumber.set(changeNumber);
94+
}
95+
96+
@Override
97+
public boolean trafficTypeExists(String trafficTypeName) {
98+
// If the multiset has [{"user",2}.{"account",0}], elementSet only returns
99+
// ["user"] (it ignores "account")
100+
return Sets.newHashSet(_concurrentTrafficTypeNameSet.elementSet()).contains(trafficTypeName);
101+
}
102+
103+
@Override
104+
public void clear() {
105+
_concurrentMap.clear();
106+
_concurrentTrafficTypeNameSet.clear();
107+
}
108+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package io.split.engine.cache;
2+
3+
import io.split.engine.experiments.ParsedSplit;
4+
5+
import java.util.Collection;
6+
import java.util.List;
7+
import java.util.Set;
8+
9+
public interface SplitCache {
10+
void put(ParsedSplit split);
11+
boolean remove(String name);
12+
ParsedSplit get(String name);
13+
Collection<ParsedSplit> getAll();
14+
Collection<ParsedSplit> getMany(List<String> names);
15+
long getChangeNumber();
16+
void setChangeNumber(long changeNumber);
17+
boolean trafficTypeExists(String trafficTypeName);
18+
void clear();
19+
}

0 commit comments

Comments
 (0)