diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml
index c153bf5cd..6ff03b06e 100644
--- a/.github/workflows/ci-cd.yml
+++ b/.github/workflows/ci-cd.yml
@@ -11,6 +11,11 @@ jobs:
maven-install:
name: Build
runs-on: ubuntu-latest
+ services:
+ redis:
+ image: redis
+ ports:
+ - 6379:6379
steps:
- name: Checkout code
uses: actions/checkout@v2
diff --git a/client/CHANGES.txt b/client/CHANGES.txt
index cf02bd4a8..aeca40583 100644
--- a/client/CHANGES.txt
+++ b/client/CHANGES.txt
@@ -1,3 +1,6 @@
+4.4.0 (Oct 29, 2021)
+- Added support for Redis to keep consistency across multiple SDK instances.
+
4.3.0 (Oct 19, 2021)
- Added support for the SDK to run with a custom implementation of it's internal storage modules, enabling customers to implement this caching in any storage technology of choice and connect it to the SDK instance itself which will use it instead of the in-memory structures.
- Fixed a possible OOM when there were too many Streaming events being captured, applying the expected limit of 20.
diff --git a/client/pom.xml b/client/pom.xml
index fe911697d..95cb80bd8 100644
--- a/client/pom.xml
+++ b/client/pom.xml
@@ -5,12 +5,17 @@
io.split.client
java-client-parent
- 4.3.0
+ 4.4.0-beta
java-client
jar
Java Client
Java SDK for Split
+
+
+ 1.0.0-beta
+
+
@@ -118,6 +123,12 @@
+
+ io.split.client
+ pluggable-storage
+ ${pluggable.storage}
+ compile
+
com.google.guava
guava
diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java
index 6e92c4939..166618fd6 100644
--- a/client/src/main/java/io/split/client/SplitClientConfig.java
+++ b/client/src/main/java/io/split/client/SplitClientConfig.java
@@ -6,8 +6,8 @@
import io.split.integrations.IntegrationsConfig;
import io.split.storages.enums.OperationMode;
import io.split.storages.enums.StorageMode;
-import io.split.storages.pluggable.CustomStorageWrapper;
import org.apache.hc.core5.http.HttpHost;
+import pluggable.CustomStorageWrapper;
import java.io.IOException;
import java.util.Properties;
diff --git a/client/src/main/java/io/split/client/SplitFactoryBuilder.java b/client/src/main/java/io/split/client/SplitFactoryBuilder.java
index b7f4dece4..dcb5a0bdd 100644
--- a/client/src/main/java/io/split/client/SplitFactoryBuilder.java
+++ b/client/src/main/java/io/split/client/SplitFactoryBuilder.java
@@ -38,18 +38,13 @@ public static SplitFactory build(String apiToken) throws IOException, URISyntaxE
*/
public static synchronized SplitFactory build(String apiToken, SplitClientConfig config) throws IOException, URISyntaxException {
ApiKeyValidator.validate(apiToken);
-
if (LocalhostSplitFactory.LOCALHOST.equals(apiToken)) {
return LocalhostSplitFactory.createLocalhostSplitFactory(config);
- } else {
- if (StorageMode.PLUGGABLE.equals(config.storageMode())){
- return new SplitFactoryImpl(apiToken, config, config.customStorageWrapper());
- }
- else {
- return new SplitFactoryImpl(apiToken, config);
- }
-
}
+ if (StorageMode.PLUGGABLE.equals(config.storageMode())){
+ return new SplitFactoryImpl(apiToken, config, config.customStorageWrapper());
+ }
+ return new SplitFactoryImpl(apiToken, config);
}
/**
diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java
index 6e72aab14..c2c41f0c4 100644
--- a/client/src/main/java/io/split/client/SplitFactoryImpl.java
+++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java
@@ -18,37 +18,33 @@
import io.split.client.interceptors.GzipEncoderRequestInterceptor;
import io.split.client.interceptors.SdkMetadataInterceptorFilter;
import io.split.client.utils.SDKMetadata;
-import io.split.storages.SegmentCacheConsumer;
-import io.split.storages.SegmentCacheProducer;
-import io.split.storages.SplitCacheConsumer;
-import io.split.storages.SplitCacheProducer;
-import io.split.storages.enums.OperationMode;
-import io.split.storages.enums.StorageMode;
-import io.split.storages.memory.InMemoryCacheImp;
-import io.split.storages.SplitCache;
-import io.split.engine.evaluator.Evaluator;
-import io.split.engine.evaluator.EvaluatorImp;
import io.split.engine.SDKReadinessGates;
import io.split.engine.common.SyncManager;
import io.split.engine.common.SyncManagerImp;
+import io.split.engine.evaluator.Evaluator;
+import io.split.engine.evaluator.EvaluatorImp;
import io.split.engine.experiments.SplitChangeFetcher;
import io.split.engine.experiments.SplitFetcher;
import io.split.engine.experiments.SplitFetcherImp;
import io.split.engine.experiments.SplitParser;
import io.split.engine.experiments.SplitSynchronizationTask;
import io.split.engine.segments.SegmentChangeFetcher;
-import io.split.storages.SegmentCache;
-import io.split.storages.memory.SegmentCacheInMemoryImpl;
import io.split.engine.segments.SegmentSynchronizationTaskImp;
import io.split.integrations.IntegrationsConfig;
-import io.split.storages.pluggable.CustomStorageWrapper;
+import io.split.storages.SegmentCache;
+import io.split.storages.SegmentCacheConsumer;
+import io.split.storages.SegmentCacheProducer;
+import io.split.storages.SplitCache;
+import io.split.storages.SplitCacheConsumer;
+import io.split.storages.SplitCacheProducer;
+import io.split.storages.enums.OperationMode;
+import io.split.storages.memory.InMemoryCacheImp;
+import io.split.storages.memory.SegmentCacheInMemoryImpl;
import io.split.storages.pluggable.adapters.UserCustomEventAdapterProducer;
import io.split.storages.pluggable.adapters.UserCustomImpressionAdapterConsumer;
import io.split.storages.pluggable.adapters.UserCustomImpressionAdapterProducer;
import io.split.storages.pluggable.adapters.UserCustomSegmentAdapterConsumer;
-import io.split.storages.pluggable.adapters.UserCustomSegmentAdapterProducer;
import io.split.storages.pluggable.adapters.UserCustomSplitAdapterConsumer;
-import io.split.storages.pluggable.adapters.UserCustomSplitAdapterProducer;
import io.split.storages.pluggable.adapters.UserCustomTelemetryAdapterProducer;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
import io.split.storages.pluggable.synchronizer.TelemetryConsumerSubmitter;
@@ -79,12 +75,12 @@
import org.apache.hc.core5.util.Timeout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import pluggable.CustomStorageWrapper;
import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
-
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
diff --git a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomEventAdapterProducer.java b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomEventAdapterProducer.java
index c560483ba..23e241580 100644
--- a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomEventAdapterProducer.java
+++ b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomEventAdapterProducer.java
@@ -4,10 +4,10 @@
import io.split.client.dtos.Metadata;
import io.split.client.events.EventsStorageProducer;
import io.split.client.utils.Json;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.EventConsumer;
import io.split.storages.pluggable.domain.PrefixAdapter;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
+import pluggable.CustomStorageWrapper;
import java.util.List;
import java.util.stream.Collectors;
diff --git a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomImpressionAdapterProducer.java b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomImpressionAdapterProducer.java
index 5d1076fe8..80fe5db96 100644
--- a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomImpressionAdapterProducer.java
+++ b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomImpressionAdapterProducer.java
@@ -7,10 +7,10 @@
import io.split.client.dtos.KeyImpression;
import io.split.client.dtos.Metadata;
import io.split.client.impressions.ImpressionsStorageProducer;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.ImpressionConsumer;
import io.split.storages.pluggable.domain.PrefixAdapter;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
+import pluggable.CustomStorageWrapper;
import java.lang.reflect.Modifier;
import java.util.Collections;
diff --git a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterConsumer.java b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterConsumer.java
index 8c78c6e34..e011421d7 100644
--- a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterConsumer.java
+++ b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterConsumer.java
@@ -1,10 +1,10 @@
package io.split.storages.pluggable.adapters;
import io.split.storages.SegmentCacheConsumer;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.PrefixAdapter;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
import io.split.storages.pluggable.utils.Helper;
+import pluggable.CustomStorageWrapper;
import java.util.Set;
diff --git a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterProducer.java b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterProducer.java
index b6e2faf7e..5afc5c1f3 100644
--- a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterProducer.java
+++ b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterProducer.java
@@ -2,10 +2,10 @@
import io.split.client.utils.Json;
import io.split.storages.SegmentCacheProducer;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.PrefixAdapter;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
import io.split.storages.pluggable.utils.Helper;
+import pluggable.CustomStorageWrapper;
import java.util.List;
diff --git a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterConsumer.java b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterConsumer.java
index 6038e59ee..9acee2984 100644
--- a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterConsumer.java
+++ b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterConsumer.java
@@ -5,12 +5,12 @@
import io.split.engine.experiments.ParsedSplit;
import io.split.engine.experiments.SplitParser;
import io.split.storages.SplitCacheConsumer;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
import io.split.storages.pluggable.domain.PrefixAdapter;
import io.split.storages.pluggable.utils.Helper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import pluggable.CustomStorageWrapper;
import java.util.ArrayList;
import java.util.Collection;
@@ -59,7 +59,6 @@ public Collection getAll() {
if(keys == null) {
return new ArrayList<>();
}
- keys = keys.stream().map(k -> k = PrefixAdapter.buildSplitKey(k)).collect(Collectors.toSet());
List wrapperResponse = _safeUserStorageWrapper.getMany(new ArrayList<>(keys));
if(wrapperResponse == null) {
return new ArrayList<>();
@@ -70,18 +69,17 @@ public Collection getAll() {
@Override
public boolean trafficTypeExists(String trafficTypeName) {
String wrapperResponse = _safeUserStorageWrapper.get(PrefixAdapter.buildTrafficTypeExists(trafficTypeName));
- boolean response = false;
if(wrapperResponse == null) {
- return response;
+ return false;
}
try {
- response = Json.fromJson(wrapperResponse, Boolean.class);
- return response;
+ Long value = Json.fromJson(wrapperResponse, Long.class);
+ return value != null && value > 0;
}
catch(Exception e) {
_log.info("Error getting boolean from String.");
}
- return response;
+ return false;
}
@Override
diff --git a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterProducer.java b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterProducer.java
index 585053fdd..190ac0af9 100644
--- a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterProducer.java
+++ b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterProducer.java
@@ -4,12 +4,12 @@
import io.split.client.utils.Json;
import io.split.engine.experiments.ParsedSplit;
import io.split.storages.SplitCacheProducer;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.PrefixAdapter;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
import io.split.storages.pluggable.utils.Helper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import pluggable.CustomStorageWrapper;
import java.util.HashSet;
import java.util.List;
diff --git a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomTelemetryAdapterProducer.java b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomTelemetryAdapterProducer.java
index 0afbcc164..6c0c00936 100644
--- a/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomTelemetryAdapterProducer.java
+++ b/client/src/main/java/io/split/storages/pluggable/adapters/UserCustomTelemetryAdapterProducer.java
@@ -1,7 +1,6 @@
package io.split.storages.pluggable.adapters;
import io.split.client.utils.SDKMetadata;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.PrefixAdapter;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
import io.split.telemetry.domain.StreamingEvent;
@@ -13,6 +12,7 @@
import io.split.telemetry.domain.enums.ResourceEnum;
import io.split.telemetry.storage.TelemetryStorageProducer;
import io.split.telemetry.utils.BucketCalculator;
+import pluggable.CustomStorageWrapper;
import static com.google.common.base.Preconditions.checkNotNull;
diff --git a/client/src/main/java/io/split/storages/pluggable/domain/PrefixAdapter.java b/client/src/main/java/io/split/storages/pluggable/domain/PrefixAdapter.java
index 5f752f833..8787aa998 100644
--- a/client/src/main/java/io/split/storages/pluggable/domain/PrefixAdapter.java
+++ b/client/src/main/java/io/split/storages/pluggable/domain/PrefixAdapter.java
@@ -19,7 +19,7 @@ public class PrefixAdapter {
private static final String INIT = "init";
public static String buildSplitKey(String name) {
- return String.format(DEFAULT_PREFIX+ SPLIT_PREFIX +"{%s}", name);
+ return String.format(DEFAULT_PREFIX+ SPLIT_PREFIX +"%s", name);
}
public static String buildSplitChangeNumber() {
@@ -27,17 +27,17 @@ public static String buildSplitChangeNumber() {
}
public static String buildGetAllSplit() {
- return DEFAULT_PREFIX+SPLITS_PREFIX+"*";
+ return DEFAULT_PREFIX+SPLIT_PREFIX+"*";
}
public static String buildTrafficTypeExists(String trafficType) {
- return String.format(DEFAULT_PREFIX+TRAFFIC_TYPE_PREFIX+"{%s}", trafficType);
+ return String.format(DEFAULT_PREFIX+TRAFFIC_TYPE_PREFIX+"%s", trafficType);
}
public static List buildFetchManySplits(List names) {
List prefixes = new ArrayList<>();
for(String name : names) {
- prefixes.add(String.format(DEFAULT_PREFIX+ SPLIT_PREFIX +"{%s}", name));
+ prefixes.add(String.format(DEFAULT_PREFIX+ SPLIT_PREFIX +"%s", name));
}
return prefixes;
}
@@ -51,7 +51,7 @@ public static String buildImpressions() {
}
public static String buildSegment(String segmentName) {
- return String.format(DEFAULT_PREFIX+SEGMENT+"{%s}", segmentName);
+ return String.format(DEFAULT_PREFIX+SEGMENT+"%s", segmentName);
}
public static String buildSegmentAll() {
@@ -59,18 +59,18 @@ public static String buildSegmentAll() {
}
public static String buildSegmentTill(String segmentName) {
- return String.format(DEFAULT_PREFIX+SEGMENT+"{%s}."+TILL, segmentName);
+ return String.format(DEFAULT_PREFIX+SEGMENT+"%s."+TILL, segmentName);
}
public static String buildTelemetryLatenciesPrefix(String method, int bucketForLatency, String sdkVersion, String machineIp, String machineName) {
- return String.format(DEFAULT_PREFIX+TELEMETRY+LATENCIES+"::{%s}/{%s}/{%s}/"+"{%s}/{%d}", sdkVersion, machineName, machineIp, method, bucketForLatency);
+ return String.format(DEFAULT_PREFIX+TELEMETRY+LATENCIES+"::%s/%s/%s/"+"%s/%d", sdkVersion, machineName, machineIp, method, bucketForLatency);
}
public static String buildTelemetryExceptionsPrefix(String method, String sdkVersion, String machineIp, String machineName) {
- return String.format(DEFAULT_PREFIX+TELEMETRY+EXCEPTIONS+"::{%s}/{%s}/{%s}/"+"{%s}", sdkVersion, machineName, machineIp, method);
+ return String.format(DEFAULT_PREFIX+TELEMETRY+EXCEPTIONS+"::%s/%s/%s/"+"%s", sdkVersion, machineName, machineIp, method);
}
public static String buildTelemetryInit(String sdkVersion, String machineIp, String machineName) {
- return String.format(DEFAULT_PREFIX+TELEMETRY+INIT+"::{%s}/{%s}/{%s}", sdkVersion, machineName, machineIp);
+ return String.format(DEFAULT_PREFIX+TELEMETRY+INIT+"::%s/%s/%s", sdkVersion, machineName, machineIp);
}
}
diff --git a/client/src/main/java/io/split/storages/pluggable/domain/SafeUserStorageWrapper.java b/client/src/main/java/io/split/storages/pluggable/domain/SafeUserStorageWrapper.java
index 2bb5cbfc6..1ee146a07 100644
--- a/client/src/main/java/io/split/storages/pluggable/domain/SafeUserStorageWrapper.java
+++ b/client/src/main/java/io/split/storages/pluggable/domain/SafeUserStorageWrapper.java
@@ -1,11 +1,10 @@
package io.split.storages.pluggable.domain;
-import io.split.storages.pluggable.CustomStorageWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import pluggable.CustomStorageWrapper;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
diff --git a/client/src/main/java/io/split/storages/pluggable/synchronizer/TelemetryConsumerSubmitter.java b/client/src/main/java/io/split/storages/pluggable/synchronizer/TelemetryConsumerSubmitter.java
index 929504658..d55cc709d 100644
--- a/client/src/main/java/io/split/storages/pluggable/synchronizer/TelemetryConsumerSubmitter.java
+++ b/client/src/main/java/io/split/storages/pluggable/synchronizer/TelemetryConsumerSubmitter.java
@@ -5,11 +5,11 @@
import io.split.client.utils.Json;
import io.split.client.utils.SDKMetadata;
import io.split.storages.enums.OperationMode;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.ConfigConsumer;
import io.split.storages.pluggable.domain.PrefixAdapter;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
import io.split.telemetry.synchronizer.TelemetrySynchronizer;
+import pluggable.CustomStorageWrapper;
import java.util.List;
import java.util.Map;
diff --git a/client/src/test/java/io/split/client/SplitClientIntegrationTest.java b/client/src/test/java/io/split/client/SplitClientIntegrationTest.java
index ba68fafa8..45ff4dcb7 100644
--- a/client/src/test/java/io/split/client/SplitClientIntegrationTest.java
+++ b/client/src/test/java/io/split/client/SplitClientIntegrationTest.java
@@ -9,7 +9,6 @@
import io.split.integrations.IntegrationsConfig;
import io.split.storages.enums.OperationMode;
import io.split.storages.enums.StorageMode;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.CustomStorageWrapperImp;
import io.split.storages.pluggable.domain.EventConsumer;
import io.split.storages.pluggable.domain.ImpressionConsumer;
diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java
index 868c646c1..4584cfc55 100644
--- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java
+++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java
@@ -3,14 +3,13 @@
import io.split.client.impressions.ImpressionsManager;
import io.split.integrations.IntegrationsConfig;
import io.split.storages.enums.OperationMode;
-import io.split.storages.enums.StorageMode;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
import io.split.telemetry.storage.TelemetryStorage;
import io.split.telemetry.synchronizer.TelemetrySynchronizer;
import junit.framework.TestCase;
import org.junit.Test;
import org.mockito.Mockito;
+import pluggable.CustomStorageWrapper;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
diff --git a/client/src/test/java/io/split/client/impressions/ImpressionsManagerImplTest.java b/client/src/test/java/io/split/client/impressions/ImpressionsManagerImplTest.java
index 3beb83d57..ee175c32a 100644
--- a/client/src/test/java/io/split/client/impressions/ImpressionsManagerImplTest.java
+++ b/client/src/test/java/io/split/client/impressions/ImpressionsManagerImplTest.java
@@ -5,7 +5,6 @@
import io.split.client.dtos.TestImpressions;
import io.split.storages.enums.OperationMode;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.telemetry.domain.enums.ImpressionsDataTypeEnum;
import io.split.telemetry.storage.InMemoryTelemetryStorage;
import io.split.telemetry.storage.TelemetryStorage;
@@ -18,6 +17,7 @@
import org.mockito.Captor;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
+import pluggable.CustomStorageWrapper;
import java.net.URISyntaxException;
import java.util.AbstractMap;
diff --git a/client/src/test/java/io/split/engine/splitter/HashingTest.java b/client/src/test/java/io/split/engine/splitter/HashingTest.java
index aafad5576..fac461bbc 100644
--- a/client/src/test/java/io/split/engine/splitter/HashingTest.java
+++ b/client/src/test/java/io/split/engine/splitter/HashingTest.java
@@ -144,8 +144,6 @@ private void collisionTest(int seed, MyHash hash, List keys) {
}
}
- System.out.println(hash + " collisions: " + collisions + " percentage: " + (100f * collisions / keys.size()));
- System.out.println(hash + " time: " + durationSum / keys.size() + " ns");
}
private void bucketTest(int seed, MyHash hash, List keys) {
@@ -161,8 +159,6 @@ private void bucketTest(int seed, MyHash hash, List keys) {
ranges[(bucket - 1) / 10]++;
}
- System.out.println(buckets);
- System.out.println(Arrays.toString(ranges));
}
private void spreadBySeed(int seed1, int seed2, MyHash hash, List keys) {
@@ -182,6 +178,5 @@ private void spreadBySeed(int seed1, int seed2, MyHash hash, List keys)
}
int collisions = bitset.cardinality();
- System.out.println(hash + " collisions " + collisions + " percentage: " + (100f * collisions / keys.size()));
}
}
diff --git a/client/src/test/java/io/split/engine/splitter/SplitterTest.java b/client/src/test/java/io/split/engine/splitter/SplitterTest.java
index e888d2fd3..5210b779e 100644
--- a/client/src/test/java/io/split/engine/splitter/SplitterTest.java
+++ b/client/src/test/java/io/split/engine/splitter/SplitterTest.java
@@ -40,7 +40,6 @@ public void generateData() {
String key = RandomStringUtils.randomAlphanumeric(keyLength);
long hash = Splitter.hash(key, seed, 1);
int bucket = Splitter.bucket(hash);
- System.out.println(Joiner.on(',').join(Lists.newArrayList(seed, key, hash, bucket)));
}
}
@@ -59,7 +58,6 @@ public void generateNonAlphaNumericData() {
String key = RandomStringUtils.random(keyLength);
long hash = Splitter.hash(key, seed, 1);
int bucket = Splitter.bucket(hash);
- System.out.println(Joiner.on(',').join(Lists.newArrayList(seed, key, hash, bucket)));
}
}
diff --git a/client/src/test/java/io/split/engine/sse/SSEClientTest.java b/client/src/test/java/io/split/engine/sse/SSEClientTest.java
index aa9e8ba97..4319ae101 100644
--- a/client/src/test/java/io/split/engine/sse/SSEClientTest.java
+++ b/client/src/test/java/io/split/engine/sse/SSEClientTest.java
@@ -37,8 +37,8 @@ public void basicUsageTest() throws URISyntaxException, InterruptedException {
CloseableHttpClient httpClient = httpClientbuilder.build();
- SSEClient sse = new SSEClient(e -> { System.out.println(e); return null; },
- s -> { System.out.println(s); return null; }, httpClient, telemetryRuntimeProducer);
+ SSEClient sse = new SSEClient(e -> null,
+ s -> null, httpClient, telemetryRuntimeProducer);
sse.open(uri);
Thread.sleep(5000);
sse.close();
diff --git a/client/src/test/java/io/split/storages/pluggable/CustomStorageWrapperImp.java b/client/src/test/java/io/split/storages/pluggable/CustomStorageWrapperImp.java
index eb16e790b..1e39bedf8 100644
--- a/client/src/test/java/io/split/storages/pluggable/CustomStorageWrapperImp.java
+++ b/client/src/test/java/io/split/storages/pluggable/CustomStorageWrapperImp.java
@@ -10,14 +10,17 @@
import io.split.client.dtos.ConditionType;
import io.split.client.dtos.Split;
import io.split.client.dtos.Status;
+import io.split.client.utils.Json;
import io.split.engine.ConditionsTestUtil;
import io.split.engine.segments.SegmentImp;
import io.split.grammar.Treatments;
import io.split.storages.pluggable.domain.ConfigConsumer;
import io.split.storages.pluggable.domain.EventConsumer;
import io.split.storages.pluggable.domain.ImpressionConsumer;
+import io.split.storages.pluggable.domain.PrefixAdapter;
import io.split.telemetry.domain.enums.MethodEnum;
import io.split.telemetry.utils.AtomicLongArray;
+import pluggable.CustomStorageWrapper;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
@@ -32,9 +35,9 @@ public class CustomStorageWrapperImp implements CustomStorageWrapper {
public static final int MAX_LATENCY_BUCKET_COUNT = 23;
private static final String TELEMETRY = "SPLITIO.telemetry";
- private static final String SPLIT = "SPLITIO.split";
+ private static final String SPLIT = "SPLITIO.split.";
private static final String SPLITS = "SPLITIO.splits.*";
- private static final String SEGMENT = "SPLITIO.segment";
+ private static final String SEGMENT = "SPLITIO.segment.";
private static final String IMPRESSIONS = "SPLITIO.impressions";
private static final String EVENTS = "SPLITIO.events";
private Map splitsStorage = new HashMap<>();
@@ -66,9 +69,7 @@ public CustomStorageWrapperImp() {
public String get(String key) throws Exception {
String value = getStorage(key);
if(value.equals(SPLIT)){
- String name = key.substring(key.indexOf("{") + 1);
- name = name.substring(0, name.indexOf("}"));
- return _json.toJson(splitsStorage.get(name));
+ return _json.toJson(splitsStorage.get(key));
}
return "";
}
@@ -79,13 +80,10 @@ public List getMany(List keys) throws Exception {
return null;
}
String value = getStorage(keys.get(0));
- keys = keys.stream().map(k -> {
- k = k.substring(k.indexOf("{") + 1);
- k = k.substring(0, k.indexOf("}"));
- return k;}).collect(Collectors.toList());
if(value.equals(SPLIT)){
- List finalKeys = keys;
- return splitsStorage.values().stream().filter(v -> finalKeys.contains(v.name)).map(_json::toJson).collect(Collectors.toList());
+ List results = new ArrayList<>();
+ keys.forEach(k -> results.add(Json.toJson(splitsStorage.get(k))));
+ return results;
}
return null;
}
@@ -113,7 +111,7 @@ public String getAndSet(String key, String item) throws Exception {
@Override
public Set getKeysByPrefix(String prefix) throws Exception {
String value = getStorage(prefix);
- if(value.equals(SPLITS)){
+ if(value.equals(SPLIT)){
return splitsStorage.keySet();
}
return null;
@@ -164,9 +162,7 @@ public long getItemsCount(String key) throws Exception {
public boolean itemContains(String key, String item) throws Exception {
String value = getStorage(key);
if(value.equals(SEGMENT)){
- String name = key.substring(key.indexOf("{") + 1);
- name = name.substring(0, name.indexOf("}"));
- SegmentImp segmentImp = segmentStorage.get(name);
+ SegmentImp segmentImp = segmentStorage.get(key);
return segmentImp.contains(item);
}
return false;
@@ -215,9 +211,9 @@ else if(key.startsWith(EVENTS))
private void updateCache(){
Condition condition = ConditionsTestUtil.makeUserDefinedSegmentCondition(ConditionType.WHITELIST,"segmentName" , Lists.newArrayList(ConditionsTestUtil.partition("on", 100)));
- segmentStorage.put("segmentName", new SegmentImp(9874654L, "segmentName", Lists.newArrayList("key", "key2")));
- splitsStorage.put("first.name", makeSplit("first.name", 123, Lists.newArrayList(condition), 456478976L));
- splitsStorage.put("second.name", makeSplit("second.name", 321, Lists.newArrayList(), 568613L));
+ segmentStorage.put(PrefixAdapter.buildSegment("segmentName"), new SegmentImp(9874654L, "segmentName", Lists.newArrayList("key", "key2")));
+ splitsStorage.put(PrefixAdapter.buildSplitKey("first.name"), makeSplit("first.name", 123, Lists.newArrayList(condition), 456478976L));
+ splitsStorage.put(PrefixAdapter.buildSplitKey("second.name"), makeSplit("second.name", 321, Lists.newArrayList(), 568613L));
}
private Split makeSplit(String name, int seed, List conditions, long changeNumber) {
diff --git a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomEventAdapterProducerTest.java b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomEventAdapterProducerTest.java
index 253d90a44..bc22a42fa 100644
--- a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomEventAdapterProducerTest.java
+++ b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomEventAdapterProducerTest.java
@@ -2,11 +2,11 @@
import io.split.client.dtos.Event;
import io.split.client.dtos.Metadata;
-import io.split.storages.pluggable.CustomStorageWrapper;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import pluggable.CustomStorageWrapper;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
diff --git a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomImpressionAdapterProducerTest.java b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomImpressionAdapterProducerTest.java
index 750b284b1..db7614930 100644
--- a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomImpressionAdapterProducerTest.java
+++ b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomImpressionAdapterProducerTest.java
@@ -2,12 +2,12 @@
import io.split.client.dtos.KeyImpression;
import io.split.client.dtos.Metadata;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import pluggable.CustomStorageWrapper;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
diff --git a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterConsumerTest.java b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterConsumerTest.java
index 7b34e5d7e..2b2e1fba4 100644
--- a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterConsumerTest.java
+++ b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterConsumerTest.java
@@ -1,13 +1,13 @@
package io.split.storages.pluggable.adapters;
import io.split.client.utils.Json;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.PrefixAdapter;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import pluggable.CustomStorageWrapper;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
diff --git a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterProducerTest.java b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterProducerTest.java
index fb94f8eae..41d05546b 100644
--- a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterProducerTest.java
+++ b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSegmentAdapterProducerTest.java
@@ -1,13 +1,13 @@
package io.split.storages.pluggable.adapters;
import io.split.client.utils.Json;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.PrefixAdapter;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import pluggable.CustomStorageWrapper;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
diff --git a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterConsumerTest.java b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterConsumerTest.java
index 5db27945a..a2126c053 100644
--- a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterConsumerTest.java
+++ b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterConsumerTest.java
@@ -7,17 +7,16 @@
import io.split.engine.experiments.ParsedSplit;
import io.split.engine.experiments.SplitParser;
import io.split.grammar.Treatments;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.PrefixAdapter;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import pluggable.CustomStorageWrapper;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -131,7 +130,7 @@ public void testGetAllNullOnGetMany() {
@Test
public void testTrafficTypeExists() {
Mockito.when(_safeUserStorageWrapper.get(PrefixAdapter.buildTrafficTypeExists("TrafficType"))).
- thenReturn(getBooleanAsJson(true));
+ thenReturn(getLongAsJson(2));
boolean result = _userCustomSplitAdapterConsumer.trafficTypeExists("TrafficType");
Assert.assertTrue(result);
}
@@ -147,7 +146,7 @@ public void testTrafficTypeExistsWithWrapperFailing() {
@Test
public void testTrafficTypeExistsWithGsonFailing() {
Mockito.when(_safeUserStorageWrapper.get(PrefixAdapter.buildTrafficTypeExists("TrafficType"))).
- thenReturn("2");
+ thenReturn("true");
boolean result = _userCustomSplitAdapterConsumer.trafficTypeExists("TrafficType");
Assert.assertFalse(result);
}
diff --git a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterProducerTest.java b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterProducerTest.java
index 2031d1c3a..baa0f17d6 100644
--- a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterProducerTest.java
+++ b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomSplitAdapterProducerTest.java
@@ -9,13 +9,13 @@
import io.split.engine.experiments.ParsedSplit;
import io.split.engine.experiments.SplitParser;
import io.split.grammar.Treatments;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.PrefixAdapter;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import pluggable.CustomStorageWrapper;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
diff --git a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomTelemetryAdapterProducerTest.java b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomTelemetryAdapterProducerTest.java
index de3ee562f..0c778fb32 100644
--- a/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomTelemetryAdapterProducerTest.java
+++ b/client/src/test/java/io/split/storages/pluggable/adapters/UserCustomTelemetryAdapterProducerTest.java
@@ -1,19 +1,12 @@
package io.split.storages.pluggable.adapters;
import io.split.client.utils.SDKMetadata;
-import io.split.storages.pluggable.CustomStorageWrapper;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
-import io.split.telemetry.domain.StreamingEvent;
-import io.split.telemetry.domain.enums.EventsDataRecordsEnum;
-import io.split.telemetry.domain.enums.HTTPLatenciesEnum;
-import io.split.telemetry.domain.enums.ImpressionsDataTypeEnum;
-import io.split.telemetry.domain.enums.LastSynchronizationRecordsEnum;
import io.split.telemetry.domain.enums.MethodEnum;
-import io.split.telemetry.domain.enums.ResourceEnum;
-import org.apache.hc.core5.http.HttpStatus;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import pluggable.CustomStorageWrapper;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
diff --git a/client/src/test/java/io/split/storages/pluggable/domain/PrefixAdapterTest.java b/client/src/test/java/io/split/storages/pluggable/domain/PrefixAdapterTest.java
index 28d85a5e1..5fb02532c 100644
--- a/client/src/test/java/io/split/storages/pluggable/domain/PrefixAdapterTest.java
+++ b/client/src/test/java/io/split/storages/pluggable/domain/PrefixAdapterTest.java
@@ -22,7 +22,7 @@ public class PrefixAdapterTest{
@Test
public void testBuildSplitKey() {
String prefix = PrefixAdapter.buildSplitKey(SPLIT_NAME);
- String expectedPrefix = String.format(DEFAULT_PREFIX+SPLIT_PREFIX+"{%s}", SPLIT_NAME);
+ String expectedPrefix = String.format(DEFAULT_PREFIX+SPLIT_PREFIX+"%s", SPLIT_NAME);
Assert.assertEquals(expectedPrefix,prefix);
}
@@ -36,22 +36,22 @@ public void testBuildSplitGetChangeNumber() {
@Test
public void testBuildGetAllSplit() {
String prefix = PrefixAdapter.buildGetAllSplit();
- String expectedPrefix = DEFAULT_PREFIX+ "splits.*";
+ String expectedPrefix = DEFAULT_PREFIX+ "split.*";
Assert.assertEquals(expectedPrefix,prefix);
}
@Test
public void testBuildTrafficTypeExists() {
String prefix = PrefixAdapter.buildTrafficTypeExists(TRAFFIC_TYPE);
- String expectedPrefix = String.format(DEFAULT_PREFIX+TRAFFIC_TYPE_PREFIX+"{%s}", TRAFFIC_TYPE);
+ String expectedPrefix = String.format(DEFAULT_PREFIX+TRAFFIC_TYPE_PREFIX+"%s", TRAFFIC_TYPE);
Assert.assertEquals(expectedPrefix,prefix);
}
@Test
public void testBuildFetchManySplits() {
List prefixes = PrefixAdapter.buildFetchManySplits(Stream.of(SPLIT_NAME+"1", SPLIT_NAME+"2").collect(Collectors.toList()));
- String expectedPrefix1 = String.format(DEFAULT_PREFIX+ SPLIT_PREFIX +"{%s}", SPLIT_NAME+"1");
- String expectedPrefix2 = String.format(DEFAULT_PREFIX+ SPLIT_PREFIX +"{%s}", SPLIT_NAME+"2");
+ String expectedPrefix1 = String.format(DEFAULT_PREFIX+ SPLIT_PREFIX +"%s", SPLIT_NAME+"1");
+ String expectedPrefix2 = String.format(DEFAULT_PREFIX+ SPLIT_PREFIX +"%s", SPLIT_NAME+"2");
Assert.assertEquals(2,prefixes.size());
Assert.assertEquals(expectedPrefix1,prefixes.get(0));
Assert.assertEquals(expectedPrefix2,prefixes.get(1));
@@ -78,13 +78,13 @@ public void testBuildSegments() {
@Test
public void testBuildTelemetryLatencies() {
- String expectedPrefix = "SPLITIO.telemetry.latencies::{sv}/{mn}/{mi}/{getTreatment}/{2}";
+ String expectedPrefix = "SPLITIO.telemetry.latencies::sv/mn/mi/getTreatment/2";
Assert.assertEquals(expectedPrefix, PrefixAdapter.buildTelemetryLatenciesPrefix("getTreatment", 2, "sv", "mi","mn"));
}
@Test
public void testBuildTelemetryExceptions() {
- String expectedPrefix = "SPLITIO.telemetry.exceptions::{sv}/{mn}/{mi}/{getTreatment}";
+ String expectedPrefix = "SPLITIO.telemetry.exceptions::sv/mn/mi/getTreatment";
Assert.assertEquals(expectedPrefix, PrefixAdapter.buildTelemetryExceptionsPrefix("getTreatment", "sv", "mi","mn"));
}
diff --git a/client/src/test/java/io/split/storages/pluggable/domain/SafeUserStorageWrapperTest.java b/client/src/test/java/io/split/storages/pluggable/domain/SafeUserStorageWrapperTest.java
index 001ae9f0d..d1b683dbd 100644
--- a/client/src/test/java/io/split/storages/pluggable/domain/SafeUserStorageWrapperTest.java
+++ b/client/src/test/java/io/split/storages/pluggable/domain/SafeUserStorageWrapperTest.java
@@ -1,11 +1,11 @@
package io.split.storages.pluggable.domain;
-import io.split.storages.pluggable.CustomStorageWrapper;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import org.slf4j.Logger;
+import pluggable.CustomStorageWrapper;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
diff --git a/client/src/test/java/io/split/storages/pluggable/synchronizer/TelemetryConsumerSubmitterTest.java b/client/src/test/java/io/split/storages/pluggable/synchronizer/TelemetryConsumerSubmitterTest.java
index d863787b5..74bc6ebd9 100644
--- a/client/src/test/java/io/split/storages/pluggable/synchronizer/TelemetryConsumerSubmitterTest.java
+++ b/client/src/test/java/io/split/storages/pluggable/synchronizer/TelemetryConsumerSubmitterTest.java
@@ -3,14 +3,12 @@
import io.split.client.ApiKeyCounter;
import io.split.client.SplitClientConfig;
import io.split.client.utils.SDKMetadata;
-import io.split.storages.pluggable.CustomStorageWrapper;
-import io.split.storages.pluggable.adapters.UserCustomTelemetryAdapterProducer;
import io.split.storages.pluggable.domain.ConfigConsumer;
import io.split.storages.pluggable.domain.SafeUserStorageWrapper;
-import io.split.telemetry.domain.Config;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
+import pluggable.CustomStorageWrapper;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml
new file mode 100644
index 000000000..b8840f28c
--- /dev/null
+++ b/pluggable-storage/pom.xml
@@ -0,0 +1,19 @@
+
+
+ 4.0.0
+
+ java-client-parent
+ io.split.client
+ 4.4.0-beta
+
+
+ 1.0.0-beta
+ pluggable-storage
+ jar
+ Package for Pluggable Storage
+ Wrapper interface to implement Pluggable Storage
+
+
+
\ No newline at end of file
diff --git a/client/src/main/java/io/split/storages/pluggable/CustomStorageWrapper.java b/pluggable-storage/src/main/java/pluggable/CustomStorageWrapper.java
similarity index 95%
rename from client/src/main/java/io/split/storages/pluggable/CustomStorageWrapper.java
rename to pluggable-storage/src/main/java/pluggable/CustomStorageWrapper.java
index 563f5194b..86a743c4b 100644
--- a/client/src/main/java/io/split/storages/pluggable/CustomStorageWrapper.java
+++ b/pluggable-storage/src/main/java/pluggable/CustomStorageWrapper.java
@@ -1,7 +1,6 @@
-package io.split.storages.pluggable;
+package pluggable;
import java.util.List;
-import java.util.Map;
import java.util.Set;
public interface CustomStorageWrapper {
diff --git a/pom.xml b/pom.xml
index d67b6f0d2..d52d1d3f1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
io.split.client
java-client-parent
- 4.3.0
+ 4.4.0-beta
@@ -72,6 +72,8 @@
testing
client
+ pluggable-storage
+ redis-wrapper
diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml
new file mode 100644
index 000000000..7e0e1b767
--- /dev/null
+++ b/redis-wrapper/pom.xml
@@ -0,0 +1,41 @@
+
+
+ 4.0.0
+
+ java-client-parent
+ io.split.client
+ 4.4.0-beta
+
+
+ redis-wrapper
+ 1.0.0-beta
+
+ 8
+ 8
+ 1.0.0-beta
+
+
+
+ io.split.client
+ pluggable-storage
+ ${pluggable.storage}
+ compile
+
+
+ redis.clients
+ jedis
+ 3.7.0
+
+
+
+ junit
+ junit
+ test
+
+
+
+
+
+
\ No newline at end of file
diff --git a/redis-wrapper/src/main/java/redis/RedisImp.java b/redis-wrapper/src/main/java/redis/RedisImp.java
new file mode 100644
index 000000000..69ce8a53f
--- /dev/null
+++ b/redis-wrapper/src/main/java/redis/RedisImp.java
@@ -0,0 +1,207 @@
+package redis;
+
+import pluggable.CustomStorageWrapper;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisPool;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+class RedisImp implements CustomStorageWrapper {
+ private static final String TELEMETRY_INIT = "SPLITIO.telemetry.init" ;
+
+ private final JedisPool jedisPool;
+ private final String prefix;
+
+ public RedisImp(JedisPool jedisPool, String prefix) {
+ this.jedisPool = jedisPool;
+ this.prefix = prefix;
+ }
+
+ @Override
+ public String get(String key) throws Exception {
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ return jedis.get(buildKeyWithPrefix(key));
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public List getMany(List keys) throws Exception {
+ if(keys == null || keys.isEmpty()){
+ return new ArrayList<>();
+ }
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ keys = keys.stream().map(key -> buildKeyWithPrefix(key)).collect(Collectors.toList());
+
+ return jedis.mget(keys.toArray(new String[keys.size()]));
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public void set(String key, String item) throws Exception {
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ if(key.contains(TELEMETRY_INIT)) {
+ String[] splittedKey = key.split("::");
+ jedis.hset(buildKeyWithPrefix(splittedKey[0]), splittedKey[1], item);
+ return;
+ }
+ jedis.set(buildKeyWithPrefix(key), item);
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public void delete(List keys) throws Exception {
+ if(keys == null || keys.isEmpty()){
+ return ;
+ }
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ keys = keys.stream().map(key -> buildKeyWithPrefix(key)).collect(Collectors.toList());
+
+ jedis.del(keys.toArray(new String[keys.size()]));
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public String getAndSet(String key, String item) throws Exception {
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ return jedis.getSet(buildKeyWithPrefix(key), item);
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public Set getKeysByPrefix(String prefix) throws Exception {
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ return jedis.keys(buildKeyWithPrefix(prefix));
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public long increment(String key, long value) throws Exception {
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ return jedis.incrBy(buildKeyWithPrefix(key), value);
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public long decrement(String key, long value) throws Exception {
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ return jedis.decrBy(buildKeyWithPrefix(key), value);
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public void pushItems(String key, List items) throws Exception {
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ jedis.rpush(buildKeyWithPrefix(key), items.toArray(new String[items.size()]));
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public List popItems(String key, long count) throws Exception {
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ return jedis.rpop(buildKeyWithPrefix(key), (int)count);
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ // Return length of redis set.
+ @Override
+ public long getItemsCount(String key) throws Exception {
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ return jedis.scard(buildKeyWithPrefix(key));
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public boolean itemContains(String key, String item) throws Exception {
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ return jedis.sismember(buildKeyWithPrefix(key), item);
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public void addItems(String key, List items) throws Exception {
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ jedis.sadd(buildKeyWithPrefix(key), items.toArray(new String[items.size()]));
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public void removeItems(String key, List items) throws Exception {
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ jedis.srem(buildKeyWithPrefix(key), items.toArray(new String[items.size()]));
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public List getItems(List keys) throws Exception {
+ if(keys == null || keys.isEmpty()){
+ return new ArrayList<>();
+ }
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ keys = keys.stream().map(key -> buildKeyWithPrefix(key)).collect(Collectors.toList());
+
+ return jedis.mget(keys.toArray(new String[keys.size()]));
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public boolean connect() throws Exception {
+ try (Jedis jedis = this.jedisPool.getResource()) {
+ return "PONG".equalsIgnoreCase(jedis.ping());
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ @Override
+ public boolean close() throws Exception {
+ try {
+ jedisPool.close();
+
+ return true;
+ } catch (Exception ex) {
+ throw new Exception(ex);
+ }
+ }
+
+ private String buildKeyWithPrefix(String key) {
+ if (!key.startsWith(this.prefix)) {
+ key = String.format("%s.%s", prefix, key);
+ }
+
+ return key;
+ }
+}
+
diff --git a/redis-wrapper/src/main/java/redis/RedisInstance.java b/redis-wrapper/src/main/java/redis/RedisInstance.java
new file mode 100644
index 000000000..0ef7e8a10
--- /dev/null
+++ b/redis-wrapper/src/main/java/redis/RedisInstance.java
@@ -0,0 +1,90 @@
+package redis;
+
+import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
+import pluggable.CustomStorageWrapper;
+import redis.clients.jedis.JedisPool;
+import redis.clients.jedis.JedisPoolConfig;
+
+public class RedisInstance {
+
+ private static final int TIMEOUT = 1000;
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ private static CustomStorageWrapper getRedisInstance(String host, int port, int timeout, String user, String password, int database, String prefix, int maxTotal) {
+ JedisPoolConfig poolConfig = new JedisPoolConfig();
+ poolConfig.setMaxTotal(maxTotal);
+ JedisPool jedisPool = new JedisPool(poolConfig, host, port, timeout, password, database);
+ return new RedisImp(jedisPool, prefix);
+ }
+
+ private static CustomStorageWrapper getRedisInstance(JedisPool jedisPool, String prefix) {
+ return new RedisImp(jedisPool, prefix);
+ }
+
+ public static final class Builder {
+ private int _timeout = TIMEOUT;
+ private String _host = "localhost";
+ private int _port = 6379;
+ private String _user = null;
+ private String _password = null;
+ private int _database = 0;
+ private String _prefix = "";
+ private JedisPool _jedisPool = null;
+ private int _maxTotal = GenericObjectPoolConfig.DEFAULT_MAX_TOTAL;
+
+ public Builder timeout(int timeout) {
+ _timeout = timeout;
+ return this;
+ }
+
+ public Builder host(String host) {
+ _host = host;
+ return this;
+ }
+
+ public Builder port(int port) {
+ _port = port;
+ return this;
+ }
+
+ public Builder user(String user) {
+ _user = user;
+ return this;
+ }
+
+ public Builder password(String password) {
+ _password = password;
+ return this;
+ }
+
+ public Builder database(int database) {
+ _database = database;
+ return this;
+ }
+
+ public Builder prefix(String prefix) {
+ _prefix = prefix;
+ return this;
+ }
+
+ public Builder jedisPool(JedisPool jedisPool) {
+ _jedisPool = jedisPool;
+ return this;
+ }
+
+ public Builder maxTotal(int _maxTotal) {
+ _maxTotal = _maxTotal;
+ return this;
+ }
+
+ public CustomStorageWrapper build() {
+ if(_jedisPool != null) {
+ return RedisInstance.getRedisInstance(_jedisPool, _prefix);
+ }
+ return RedisInstance.getRedisInstance(_host, _port, _timeout, _user, _password, _database, _prefix, _maxTotal);
+ }
+ }
+}
diff --git a/redis-wrapper/src/test/java/redis/RedisImpTest.java b/redis-wrapper/src/test/java/redis/RedisImpTest.java
new file mode 100644
index 000000000..06f34658b
--- /dev/null
+++ b/redis-wrapper/src/test/java/redis/RedisImpTest.java
@@ -0,0 +1,64 @@
+package redis;
+
+import org.junit.Assert;
+import org.junit.Test;
+import pluggable.CustomStorageWrapper;
+import redis.clients.jedis.JedisPool;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class RedisImpTest {
+
+ @Test
+ public void testSetAndGet() throws Exception {
+ Map map = new HashMap<>();
+ map.put("test-5", "5");
+ map.put("test-6", "6");
+ map.put("test-7", "7");
+ map.put("test-8", "8");
+
+ CustomStorageWrapper storageWrapper = new RedisImp(new JedisPool(), "test-prefix:.");
+
+ for (Map.Entry entry : map.entrySet()) {
+ storageWrapper.set(entry.getKey(), entry.getValue());
+ }
+
+ String result = storageWrapper.get("test-7");
+
+ Assert.assertEquals("7", result);
+
+ storageWrapper.delete(new ArrayList<>(map.keySet()));
+ }
+
+ @Test
+ public void testSetAndGetMany() throws Exception {
+ Map map = new HashMap<>();
+ map.put("test-5", "5");
+ map.put("test-6", "6");
+ map.put("test-7", "7");
+ map.put("test-8", "8");
+
+ CustomStorageWrapper storageWrapper = new RedisImp(new JedisPool(), "test-prefix:.");
+
+ for (Map.Entry entry : map.entrySet()) {
+ storageWrapper.set(entry.getKey(), entry.getValue());
+ }
+
+ ArrayList keys = new ArrayList<>();
+ keys.add("test-5");
+ keys.add("test-6");
+ keys.add("test-10");
+ List expectedResult = Stream.of("5", "6", null).collect(Collectors.toList());
+ List result = storageWrapper.getMany(keys);
+
+ Assert.assertEquals(expectedResult, result);
+
+ storageWrapper.delete(new ArrayList<>(map.keySet()));
+ }
+}
+
diff --git a/redis-wrapper/src/test/java/redis/RedisInstanceTest.java b/redis-wrapper/src/test/java/redis/RedisInstanceTest.java
new file mode 100644
index 000000000..b42292fdc
--- /dev/null
+++ b/redis-wrapper/src/test/java/redis/RedisInstanceTest.java
@@ -0,0 +1,30 @@
+package redis;
+
+import org.junit.Assert;
+import org.junit.Test;
+import pluggable.CustomStorageWrapper;
+import redis.clients.jedis.JedisPool;
+
+public class RedisInstanceTest {
+
+ @Test
+ public void testRedisInstanceBuilder() {
+ CustomStorageWrapper redisInstance = RedisInstance.builder()
+ .host("localhost")
+ .timeout(1500)
+ .database(0)
+ .build();
+ Assert.assertNotNull(redisInstance);
+ }
+
+ @Test
+ public void testRedisInstanceBuilderWithJedisPool() {
+ JedisPool jedisPool = new JedisPool();
+ CustomStorageWrapper redisInstance = RedisInstance.builder()
+ .jedisPool(jedisPool)
+ .prefix("test")
+ .build();
+ Assert.assertNotNull(redisInstance);
+ }
+
+}
\ No newline at end of file
diff --git a/testing/pom.xml b/testing/pom.xml
index 0d5014844..27bcfd751 100644
--- a/testing/pom.xml
+++ b/testing/pom.xml
@@ -6,7 +6,7 @@
io.split.client
java-client-parent
- 4.3.0
+ 4.4.0-beta
java-client-testing