From d76fa70d6dbf4f4ae9a7e4a4d79ed5e2f90708b5 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 16 Aug 2023 22:39:27 -0300 Subject: [PATCH 01/14] [SDKS-7385] Add InputStream config and InputStreamProvider, to use localhost mode inside a jar --- .../JsonLocalhostSplitChangeFetcher.java | 27 ++++------- .../io/split/client/SplitClientConfig.java | 27 ++++++++++- .../io/split/client/SplitFactoryImpl.java | 45 ++++++++++++++++--- .../YamlLocalhostSplitChangeFetcher.java | 23 +++------- .../client/utils/FileInputStreamProvider.java | 19 ++++++++ .../io/split/client/utils/FileTypeEnum.java | 7 +++ .../client/utils/InputStreamProvider.java | 9 ++++ .../client/utils/InputStreamProviderImp.java | 17 +++++++ .../JsonLocalhostSplitChangeFetcherTest.java | 39 +++++++++++----- .../YamlLocalhostSplitChangeFetcherTest.java | 7 ++- .../common/LocalhostSynchronizerTest.java | 9 +++- .../experiments/SplitFetcherImpTest.java | 7 ++- .../SegmentSynchronizationTaskImpTest.java | 11 ++++- 13 files changed, 187 insertions(+), 60 deletions(-) create mode 100644 client/src/main/java/io/split/client/utils/FileInputStreamProvider.java create mode 100644 client/src/main/java/io/split/client/utils/FileTypeEnum.java create mode 100644 client/src/main/java/io/split/client/utils/InputStreamProvider.java create mode 100644 client/src/main/java/io/split/client/utils/InputStreamProviderImp.java diff --git a/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java b/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java index 9b42fa4f2..2a1be8820 100644 --- a/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java @@ -2,6 +2,7 @@ import com.google.gson.stream.JsonReader; import io.split.client.dtos.SplitChange; +import io.split.client.utils.InputStreamProvider; import io.split.client.utils.Json; import io.split.client.utils.LocalhostSanitizer; import io.split.engine.common.FetchOptions; @@ -9,9 +10,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; +import java.io.BufferedReader; +import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -20,32 +20,23 @@ public class JsonLocalhostSplitChangeFetcher implements SplitChangeFetcher { private static final Logger _log = LoggerFactory.getLogger(JsonLocalhostSplitChangeFetcher.class); - private final File _file; + private final InputStreamProvider _inputStreamProvider; private byte [] lastHash; - public JsonLocalhostSplitChangeFetcher(String filePath) { - _file = new File(filePath); + public JsonLocalhostSplitChangeFetcher(InputStreamProvider inputStreamProvider) { + _inputStreamProvider = inputStreamProvider; lastHash = new byte[0]; } @Override public SplitChange fetch(long since, FetchOptions options) { - try { - JsonReader jsonReader = new JsonReader(new FileReader(_file)); + BufferedReader streamReader = new BufferedReader(new InputStreamReader(_inputStreamProvider.get(), "UTF-8")); + JsonReader jsonReader = new JsonReader(streamReader); SplitChange splitChange = Json.fromJson(jsonReader, SplitChange.class); return processSplitChange(splitChange, since); - } catch (FileNotFoundException f){ - _log.warn(String.format("There was no file named %s found. " + - "We created a split client that returns default treatments for all feature flags for all of your users. " + - "If you wish to return a specific treatment for a feature flag, enter the name of that feature flag name and " + - "treatment name separated by whitespace in %s; one pair per line. Empty lines or lines starting with '#' are " + - "considered comments", - _file.getPath(), _file.getPath()), f); - throw new IllegalStateException("Problem fetching splitChanges: " + f.getMessage(), f); } catch (Exception e) { - _log.warn(String.format("Problem to fetch split change using the file %s", - _file.getPath()), e); + _log.warn(String.format("Problem to fetch split change using a file"), e); throw new IllegalStateException("Problem fetching splitChanges: " + e.getMessage(), e); } } diff --git a/client/src/main/java/io/split/client/SplitClientConfig.java b/client/src/main/java/io/split/client/SplitClientConfig.java index b362a2de4..4d04b5897 100644 --- a/client/src/main/java/io/split/client/SplitClientConfig.java +++ b/client/src/main/java/io/split/client/SplitClientConfig.java @@ -2,6 +2,7 @@ import io.split.client.impressions.ImpressionListener; import io.split.client.impressions.ImpressionsManager; +import io.split.client.utils.FileTypeEnum; import io.split.integrations.IntegrationsConfig; import io.split.storages.enums.OperationMode; import io.split.storages.enums.StorageMode; @@ -9,6 +10,7 @@ import pluggable.CustomStorageWrapper; import java.io.IOException; +import java.io.InputStream; import java.util.Properties; import java.util.concurrent.ThreadFactory; @@ -49,6 +51,8 @@ public class SplitClientConfig { private final int _maxStringLength; private final boolean _destroyOnShutDown; private final String _splitFile; + private final FileTypeEnum _fileType; + private final InputStream _inputStream; private final String _segmentDirectory; private final IntegrationsConfig _integrationsConfig; private final boolean _streamingEnabled; @@ -81,7 +85,6 @@ public class SplitClientConfig { public static String splitSdkVersion; private final long _lastSeenCacheSize; - public static Builder builder() { return new Builder(); } @@ -111,6 +114,8 @@ private SplitClientConfig(String endpoint, int maxStringLength, boolean destroyOnShutDown, String splitFile, + FileTypeEnum fileType, + InputStream inputStream, String segmentDirectory, IntegrationsConfig integrationsConfig, boolean streamingEnabled, @@ -159,6 +164,8 @@ private SplitClientConfig(String endpoint, _maxStringLength = maxStringLength; _destroyOnShutDown = destroyOnShutDown; _splitFile = splitFile; + _fileType = fileType; + _inputStream = inputStream; _segmentDirectory = segmentDirectory; _integrationsConfig = integrationsConfig; _streamingEnabled = streamingEnabled; @@ -301,6 +308,14 @@ public String splitFile() { return _splitFile; } + public FileTypeEnum fileType() { + return _fileType; + } + + public InputStream inputStream(){ + return _inputStream; + } + public String segmentDirectory() { return _segmentDirectory; } @@ -394,6 +409,8 @@ public static final class Builder { private int _maxStringLength = 250; private boolean _destroyOnShutDown = true; private String _splitFile = null; + private FileTypeEnum _fileType = null; + private InputStream _inputStream = null; private String _segmentDirectory = null; private IntegrationsConfig _integrationsConfig = null; private boolean _streamingEnabled = true; @@ -748,6 +765,12 @@ public Builder splitFile(String splitFile) { return this; } + public Builder splitFile(InputStream inputStream, FileTypeEnum fileType) { + _fileType = fileType; + _inputStream = inputStream; + return this; + } + /** * Set the location of the directory where are the segment json files for localhost mode. * This setting is optional. @@ -1005,6 +1028,8 @@ public SplitClientConfig build() { _maxStringLength, _destroyOnShutDown, _splitFile, + _fileType, + _inputStream, _segmentDirectory, _integrationsConfig, _streamingEnabled, diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 3c46ff7fd..5827b1e1a 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -30,6 +30,9 @@ import io.split.client.interceptors.GzipDecoderResponseInterceptor; import io.split.client.interceptors.GzipEncoderRequestInterceptor; import io.split.client.interceptors.SdkMetadataInterceptorFilter; +import io.split.client.utils.FileInputStreamProvider; +import io.split.client.utils.InputStreamProvider; +import io.split.client.utils.InputStreamProviderImp; import io.split.client.utils.SDKMetadata; import io.split.engine.SDKReadinessGates; import io.split.engine.common.ConsumerSyncManager; @@ -366,16 +369,44 @@ protected SplitFactoryImpl(SplitClientConfig config) { config.getThreadFactory()); // SplitFetcher - SplitChangeFetcher splitChangeFetcher; + SplitChangeFetcher splitChangeFetcher = new LegacyLocalhostSplitChangeFetcher(config.splitFile()); + InputStreamProvider inputStreamProvider; String splitFile = config.splitFile(); - if (splitFile != null && splitFile.toLowerCase().endsWith(".json")){ - splitChangeFetcher = new JsonLocalhostSplitChangeFetcher(config.splitFile()); - } else if (splitFile != null && !splitFile.isEmpty() && (splitFile.endsWith(".yaml") || splitFile.endsWith(".yml"))) { - splitChangeFetcher = new YamlLocalhostSplitChangeFetcher(splitFile); + if (splitFile != null) { + try { + if (splitFile.toLowerCase().endsWith(".json")) { + inputStreamProvider = new FileInputStreamProvider(splitFile); + splitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); + } else if (!splitFile.isEmpty() && (splitFile.endsWith(".yaml") || splitFile.endsWith(".yml"))) { + inputStreamProvider = new FileInputStreamProvider(splitFile); + splitChangeFetcher = new YamlLocalhostSplitChangeFetcher(inputStreamProvider); + } + } catch (Exception e) { + _log.warn(String.format("There was no file named %s found. " + + "We created a split client that returns default treatments for all feature flags for all of your users. " + + "If you wish to return a specific treatment for a feature flag, enter the name of that feature flag name and " + + "treatment name separated by whitespace in %s; one pair per line. Empty lines or lines starting with '#' are " + + "considered comments", + splitFile, splitFile), e); + } + } else if (config.inputStream() != null) { + inputStreamProvider = new InputStreamProviderImp(config.inputStream()); + if (config.fileType() != null) { + switch (config.fileType()) { + case JSON: + splitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); + break; + case YAML: + splitChangeFetcher = new YamlLocalhostSplitChangeFetcher(inputStreamProvider); + break; + } + } else { + _log.warn("Should add an fileType in the config if there is an inputStream"); + } } else { - splitChangeFetcher = new LegacyLocalhostSplitChangeFetcher(config.splitFile()); + _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile doesn't add it in the config."); } - + SplitParser splitParser = new SplitParser(); _splitFetcher = new SplitFetcherImp(splitChangeFetcher, splitParser, splitCache, _telemetryStorageProducer); diff --git a/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java b/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java index abde47d73..44c47c9dc 100644 --- a/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java @@ -5,16 +5,15 @@ import io.split.client.dtos.Split; import io.split.client.dtos.SplitChange; import io.split.client.dtos.Status; +import io.split.client.utils.InputStreamProvider; import io.split.client.utils.LocalhostConstants; import io.split.engine.common.FetchOptions; import io.split.engine.experiments.SplitChangeFetcher; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.Yaml; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -27,17 +26,17 @@ public class YamlLocalhostSplitChangeFetcher implements SplitChangeFetcher { private static final Logger _log = LoggerFactory.getLogger(YamlLocalhostSplitChangeFetcher.class); - private final File _splitFile; + private final InputStreamProvider _inputStreamProvider; - public YamlLocalhostSplitChangeFetcher(String filePath) { - _splitFile = new File(filePath); + public YamlLocalhostSplitChangeFetcher(InputStreamProvider inputStreamProvider) { + _inputStreamProvider = inputStreamProvider; } @Override public SplitChange fetch(long since, FetchOptions options) { try { Yaml yaml = new Yaml(); - List>> yamlSplits = yaml.load(new FileReader(_splitFile)); + List>> yamlSplits = yaml.load(_inputStreamProvider.get()); SplitChange splitChange = new SplitChange(); splitChange.splits = new ArrayList<>(); for(Map> aSplit : yamlSplits) { @@ -76,16 +75,8 @@ public SplitChange fetch(long since, FetchOptions options) { splitChange.till = since; splitChange.since = since; return splitChange; - } catch (FileNotFoundException f) { - _log.warn(String.format("There was no file named %s found. We created a split client that returns default treatments " + - "for all feature flags for all of your users. If you wish to return a specific treatment for a feature flag, " + - "enter the name of that feature flag name and treatment name separated by whitespace in %s; one pair per line. " + - "Empty lines or lines starting with '#' are considered comments", - _splitFile.getPath(), _splitFile.getPath()), f); - throw new IllegalStateException("Problem fetching splitChanges: " + f.getMessage(), f); } catch (Exception e) { - _log.warn(String.format("Problem to fetch split change using the file %s", - _splitFile.getPath()), e); + _log.warn(String.format("Problem to fetch split change using a file"), e); throw new IllegalStateException("Problem fetching splitChanges: " + e.getMessage(), e); } } diff --git a/client/src/main/java/io/split/client/utils/FileInputStreamProvider.java b/client/src/main/java/io/split/client/utils/FileInputStreamProvider.java new file mode 100644 index 000000000..a9ced73e7 --- /dev/null +++ b/client/src/main/java/io/split/client/utils/FileInputStreamProvider.java @@ -0,0 +1,19 @@ +package io.split.client.utils; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; + +public class FileInputStreamProvider implements InputStreamProvider { + + private final String _fileName; + + public FileInputStreamProvider(String fileName) { + _fileName = fileName; + } + + @Override + public InputStream get() throws FileNotFoundException { + return new FileInputStream(_fileName); + } +} diff --git a/client/src/main/java/io/split/client/utils/FileTypeEnum.java b/client/src/main/java/io/split/client/utils/FileTypeEnum.java new file mode 100644 index 000000000..8084541cb --- /dev/null +++ b/client/src/main/java/io/split/client/utils/FileTypeEnum.java @@ -0,0 +1,7 @@ +package io.split.client.utils; + +public enum FileTypeEnum { + LEGACY, + YAML, + JSON +} diff --git a/client/src/main/java/io/split/client/utils/InputStreamProvider.java b/client/src/main/java/io/split/client/utils/InputStreamProvider.java new file mode 100644 index 000000000..8f23b50c8 --- /dev/null +++ b/client/src/main/java/io/split/client/utils/InputStreamProvider.java @@ -0,0 +1,9 @@ +package io.split.client.utils; + +import java.io.FileNotFoundException; +import java.io.InputStream; + +public interface InputStreamProvider { + + public InputStream get() throws FileNotFoundException; +} diff --git a/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java b/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java new file mode 100644 index 000000000..07ad240f4 --- /dev/null +++ b/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java @@ -0,0 +1,17 @@ +package io.split.client.utils; + +import java.io.FileNotFoundException; +import java.io.InputStream; + +public class InputStreamProviderImp implements InputStreamProvider { + private InputStream _inputStream; + + public InputStreamProviderImp(InputStream inputStream){ + _inputStream = inputStream; + } + + @Override + public InputStream get() throws FileNotFoundException { + return _inputStream; + } +} \ No newline at end of file diff --git a/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java index 164da7740..ccca3b7bd 100644 --- a/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java @@ -4,6 +4,9 @@ import io.split.client.dtos.Split; import io.split.client.dtos.SplitChange; import io.split.client.dtos.Status; +import io.split.client.utils.FileInputStreamProvider; +import io.split.client.utils.InputStreamProvider; +import io.split.client.utils.InputStreamProviderImp; import io.split.engine.common.FetchOptions; import org.junit.Assert; import org.junit.Rule; @@ -12,7 +15,10 @@ import org.mockito.Mockito; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.util.List; import java.util.Optional; @@ -27,8 +33,10 @@ public class JsonLocalhostSplitChangeFetcherTest { private String TEST_4 = "{\"splits\":[{\"trafficTypeName\":\"user\",\"name\":\"SPLIT_1\",\"trafficAllocation\":100,\"trafficAllocationSeed\":-1780071202,\"seed\":-1442762199,\"status\":\"ACTIVE\",\"killed\":false,\"defaultTreatment\":\"off\",\"changeNumber\":1675443537882,\"algo\":2,\"configurations\":{},\"conditions\":[{\"conditionType\":\"ROLLOUT\",\"matcherGroup\":{\"combiner\":\"AND\",\"matchers\":[{\"keySelector\":{\"trafficType\":\"user\",\"attribute\":null},\"matcherType\":\"ALL_KEYS\",\"negate\":false,\"userDefinedSegmentMatcherData\":null,\"whitelistMatcherData\":null,\"unaryNumericMatcherData\":null,\"betweenMatcherData\":null,\"booleanMatcherData\":null,\"dependencyMatcherData\":null,\"stringMatcherData\":null}]},\"partitions\":[{\"treatment\":\"on\",\"size\":0},{\"treatment\":\"off\",\"size\":100}],\"label\":\"default rule\"}]}],\"since\":-1,\"till\":445345}"; private String TEST_5 = "{\"splits\":[{\"trafficTypeName\":\"user\",\"name\":\"SPLIT_1\",\"trafficAllocation\":100,\"trafficAllocationSeed\":-1780071202,\"seed\":-1442762199,\"status\":\"ACTIVE\",\"killed\":false,\"defaultTreatment\":\"off\",\"changeNumber\":1675443537882,\"algo\":2,\"configurations\":{},\"conditions\":[{\"conditionType\":\"ROLLOUT\",\"matcherGroup\":{\"combiner\":\"AND\",\"matchers\":[{\"keySelector\":{\"trafficType\":\"user\",\"attribute\":null},\"matcherType\":\"ALL_KEYS\",\"negate\":false,\"userDefinedSegmentMatcherData\":null,\"whitelistMatcherData\":null,\"unaryNumericMatcherData\":null,\"betweenMatcherData\":null,\"booleanMatcherData\":null,\"dependencyMatcherData\":null,\"stringMatcherData\":null}]},\"partitions\":[{\"treatment\":\"on\",\"size\":0},{\"treatment\":\"off\",\"size\":100}],\"label\":\"default rule\"}]},{\"trafficTypeName\":\"user\",\"name\":\"SPLIT_2\",\"trafficAllocation\":100,\"trafficAllocationSeed\":-1780071202,\"seed\":-1442762199,\"status\":\"ACTIVE\",\"killed\":false,\"defaultTreatment\":\"off\",\"changeNumber\":1675443537882,\"algo\":2,\"configurations\":{},\"conditions\":[{\"conditionType\":\"ROLLOUT\",\"matcherGroup\":{\"combiner\":\"AND\",\"matchers\":[{\"keySelector\":{\"trafficType\":\"user\",\"attribute\":null},\"matcherType\":\"ALL_KEYS\",\"negate\":false,\"userDefinedSegmentMatcherData\":null,\"whitelistMatcherData\":null,\"unaryNumericMatcherData\":null,\"betweenMatcherData\":null,\"booleanMatcherData\":null,\"dependencyMatcherData\":null,\"stringMatcherData\":null}]},\"partitions\":[{\"treatment\":\"on\",\"size\":0},{\"treatment\":\"off\",\"size\":100}],\"label\":\"default rule\"}]}],\"since\":-1,\"till\":-1}"; @Test - public void testParseSplitChange(){ - JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher("src/test/resources/split_init.json"); + public void testParseSplitChange() throws FileNotFoundException { + InputStream inputStream = new FileInputStream("src/test/resources/split_init.json"); + InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); + JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); SplitChange splitChange = localhostSplitChangeFetcher.fetch(-1L, fetchOptions); @@ -40,8 +48,10 @@ public void testParseSplitChange(){ } @Test - public void testSinceAndTillSanitization(){ - JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher("src/test/resources/sanitizer/splitChangeTillSanitization.json"); + public void testSinceAndTillSanitization() throws FileNotFoundException { + InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangeTillSanitization.json"); + InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); + JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); SplitChange splitChange = localhostSplitChangeFetcher.fetch(-1L, fetchOptions); @@ -51,8 +61,10 @@ public void testSinceAndTillSanitization(){ } @Test - public void testSplitChangeWithoutSplits(){ - JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher("src/test/resources/sanitizer/splitChangeWithoutSplits.json"); + public void testSplitChangeWithoutSplits() throws FileNotFoundException { + InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangeWithoutSplits.json"); + InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); + JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); SplitChange splitChange = localhostSplitChangeFetcher.fetch(-1L, fetchOptions); @@ -61,8 +73,10 @@ public void testSplitChangeWithoutSplits(){ } @Test - public void testSplitChangeSplitsToSanitize(){ - JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher("src/test/resources/sanitizer/splitChangeSplitsToSanitize.json"); + public void testSplitChangeSplitsToSanitize() throws FileNotFoundException { + InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangeSplitsToSanitize.json"); + InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); + JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); SplitChange splitChange = localhostSplitChangeFetcher.fetch(-1L, fetchOptions); @@ -76,8 +90,10 @@ public void testSplitChangeSplitsToSanitize(){ } @Test - public void testSplitChangeSplitsToSanitizeMatchersNull(){ - JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher("src/test/resources/sanitizer/splitChangerMatchersNull.json"); + public void testSplitChangeSplitsToSanitizeMatchersNull() throws FileNotFoundException { + InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangerMatchersNull.json"); + InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); + JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); SplitChange splitChange = localhostSplitChangeFetcher.fetch(-1L, fetchOptions); @@ -98,7 +114,8 @@ public void testSplitChangeSplitsDifferentScenarios() throws IOException { byte[] test = TEST_0.getBytes(); com.google.common.io.Files.write(test, file); - JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(file.getAbsolutePath()); + InputStreamProvider inputStreamProvider = new FileInputStreamProvider(file.getAbsolutePath()); + JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); // 0) The CN from storage is -1, till and since are -1, and sha doesn't exist in the hash. It's going to return a split change with updates. diff --git a/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java index 4f89012ef..57b6d320d 100644 --- a/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java @@ -2,6 +2,8 @@ import io.split.client.dtos.Split; import io.split.client.dtos.SplitChange; +import io.split.client.utils.FileInputStreamProvider; +import io.split.client.utils.InputStreamProvider; import io.split.client.utils.LocalhostUtils; import io.split.engine.common.FetchOptions; import org.junit.Assert; @@ -12,7 +14,9 @@ import org.yaml.snakeyaml.Yaml; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.io.InputStream; import java.io.StringWriter; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -58,7 +62,8 @@ public void testParseSplitChange() throws IOException { yaml.dump(allSplits, writer); LocalhostUtils.writeFile(file, writer); - YamlLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new YamlLocalhostSplitChangeFetcher(file.getAbsolutePath()); + InputStreamProvider inputStreamProvider = new FileInputStreamProvider(file.getAbsolutePath()); + YamlLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new YamlLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); SplitChange splitChange = localhostSplitChangeFetcher.fetch(-1L, fetchOptions); diff --git a/client/src/test/java/io/split/engine/common/LocalhostSynchronizerTest.java b/client/src/test/java/io/split/engine/common/LocalhostSynchronizerTest.java index 3d303845e..ed77888f0 100644 --- a/client/src/test/java/io/split/engine/common/LocalhostSynchronizerTest.java +++ b/client/src/test/java/io/split/engine/common/LocalhostSynchronizerTest.java @@ -2,6 +2,8 @@ import io.split.client.LocalhostSegmentChangeFetcher; import io.split.client.JsonLocalhostSplitChangeFetcher; +import io.split.client.utils.FileInputStreamProvider; +import io.split.client.utils.InputStreamProvider; import io.split.engine.experiments.SplitChangeFetcher; import io.split.engine.experiments.SplitFetcher; import io.split.engine.experiments.SplitFetcherImp; @@ -20,15 +22,18 @@ import org.junit.Test; import org.mockito.Mockito; +import java.io.FileNotFoundException; + public class LocalhostSynchronizerTest { private static final TelemetryStorage TELEMETRY_STORAGE_NOOP = Mockito.mock(NoopTelemetryStorage.class); @Test - public void testSyncAll() { + public void testSyncAll() throws FileNotFoundException { SplitCache splitCacheProducer = new InMemoryCacheImp(); - SplitChangeFetcher splitChangeFetcher = new JsonLocalhostSplitChangeFetcher("src/test/resources/split_init.json"); + InputStreamProvider inputStreamProvider = new FileInputStreamProvider("src/test/resources/split_init.json"); + SplitChangeFetcher splitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); SplitParser splitParser = new SplitParser(); SplitFetcher splitFetcher = new SplitFetcherImp(splitChangeFetcher, splitParser, splitCacheProducer, TELEMETRY_STORAGE_NOOP); diff --git a/client/src/test/java/io/split/engine/experiments/SplitFetcherImpTest.java b/client/src/test/java/io/split/engine/experiments/SplitFetcherImpTest.java index d838cc0de..643ce86b8 100644 --- a/client/src/test/java/io/split/engine/experiments/SplitFetcherImpTest.java +++ b/client/src/test/java/io/split/engine/experiments/SplitFetcherImpTest.java @@ -1,6 +1,8 @@ package io.split.engine.experiments; import io.split.client.JsonLocalhostSplitChangeFetcher; +import io.split.client.utils.FileInputStreamProvider; +import io.split.client.utils.InputStreamProvider; import io.split.engine.common.FetchOptions; import io.split.storages.SplitCacheProducer; import io.split.storages.memory.InMemoryCacheImp; @@ -15,10 +17,11 @@ public class SplitFetcherImpTest { private static final TelemetryStorage TELEMETRY_STORAGE_NOOP = Mockito.mock(NoopTelemetryStorage.class); @Test - public void testLocalHost(){ + public void testLocalHost() { SplitCacheProducer splitCacheProducer = new InMemoryCacheImp(); - SplitChangeFetcher splitChangeFetcher = new JsonLocalhostSplitChangeFetcher("src/test/resources/split_init.json"); + InputStreamProvider inputStreamProvider = new FileInputStreamProvider("src/test/resources/split_init.json"); + SplitChangeFetcher splitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); SplitParser splitParser = new SplitParser(); FetchOptions fetchOptions = new FetchOptions.Builder().build(); SplitFetcher splitFetcher = new SplitFetcherImp(splitChangeFetcher, splitParser, splitCacheProducer, TELEMETRY_STORAGE_NOOP); diff --git a/client/src/test/java/io/split/engine/segments/SegmentSynchronizationTaskImpTest.java b/client/src/test/java/io/split/engine/segments/SegmentSynchronizationTaskImpTest.java index f9e1e354d..50ce80f2f 100644 --- a/client/src/test/java/io/split/engine/segments/SegmentSynchronizationTaskImpTest.java +++ b/client/src/test/java/io/split/engine/segments/SegmentSynchronizationTaskImpTest.java @@ -3,6 +3,8 @@ import com.google.common.collect.Maps; import io.split.client.LocalhostSegmentChangeFetcher; import io.split.client.JsonLocalhostSplitChangeFetcher; +import io.split.client.utils.InputStreamProvider; +import io.split.client.utils.InputStreamProviderImp; import io.split.engine.common.FetchOptions; import io.split.engine.experiments.SplitChangeFetcher; import io.split.engine.experiments.SplitFetcher; @@ -24,6 +26,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.List; @@ -145,11 +150,13 @@ public void testFetchAllAsynchronousAndGetTrue() throws NoSuchFieldException, Il } @Test - public void testLocalhostSegmentChangeFetcher() throws InterruptedException { + public void testLocalhostSegmentChangeFetcher() throws InterruptedException, FileNotFoundException { SplitCache splitCacheProducer = new InMemoryCacheImp(); - SplitChangeFetcher splitChangeFetcher = new JsonLocalhostSplitChangeFetcher("src/test/resources/split_init.json"); + InputStream inputStream = new FileInputStream("src/test/resources/split_init.json"); + InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); + SplitChangeFetcher splitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); SplitParser splitParser = new SplitParser(); FetchOptions fetchOptions = new FetchOptions.Builder().build(); SplitFetcher splitFetcher = new SplitFetcherImp(splitChangeFetcher, splitParser, splitCacheProducer, TELEMETRY_STORAGE_NOOP); From cfde3f7c374d357849d113f50bd3f4e0d457fceb Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Wed, 30 Aug 2023 19:06:11 -0300 Subject: [PATCH 02/14] [7445] Add InputStreamProviderException, add getInputStreamProviderAndFileType in SplitFactoryImpl and some improvements --- .../JsonLocalhostSplitChangeFetcher.java | 10 ++- .../io/split/client/SplitFactoryImpl.java | 84 +++++++++++-------- .../InputStreamProviderException.java | 14 ++++ .../client/utils/FileInputStreamProvider.java | 12 ++- .../client/utils/InputStreamProvider.java | 5 +- .../client/utils/InputStreamProviderImp.java | 5 +- .../io/split/client/utils/LocalhostPair.java | 20 +++++ .../YamlLocalhostSplitChangeFetcherTest.java | 2 - 8 files changed, 103 insertions(+), 49 deletions(-) create mode 100644 client/src/main/java/io/split/client/exceptions/InputStreamProviderException.java create mode 100644 client/src/main/java/io/split/client/utils/LocalhostPair.java diff --git a/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java b/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java index 2a1be8820..41ca8f06b 100644 --- a/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java @@ -2,6 +2,7 @@ import com.google.gson.stream.JsonReader; import io.split.client.dtos.SplitChange; +import io.split.client.exceptions.InputStreamProviderException; import io.split.client.utils.InputStreamProvider; import io.split.client.utils.Json; import io.split.client.utils.LocalhostSanitizer; @@ -12,7 +13,6 @@ import java.io.BufferedReader; import java.io.InputStreamReader; -import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; @@ -31,17 +31,19 @@ public JsonLocalhostSplitChangeFetcher(InputStreamProvider inputStreamProvider) @Override public SplitChange fetch(long since, FetchOptions options) { try { - BufferedReader streamReader = new BufferedReader(new InputStreamReader(_inputStreamProvider.get(), "UTF-8")); - JsonReader jsonReader = new JsonReader(streamReader); + JsonReader jsonReader = new JsonReader(new BufferedReader(new InputStreamReader(_inputStreamProvider.get(), "UTF-8"))); SplitChange splitChange = Json.fromJson(jsonReader, SplitChange.class); return processSplitChange(splitChange, since); + } catch (InputStreamProviderException i) { + _log.warn(String.format("Problem to fetch split change using file named %s", i.getFileName())); + throw new IllegalStateException("Problem fetching splitChanges: " + i.getMessage(), i); } catch (Exception e) { _log.warn(String.format("Problem to fetch split change using a file"), e); throw new IllegalStateException("Problem fetching splitChanges: " + e.getMessage(), e); } } - private SplitChange processSplitChange(SplitChange splitChange, long changeNumber) throws NoSuchAlgorithmException, UnsupportedEncodingException { + private SplitChange processSplitChange(SplitChange splitChange, long changeNumber) throws NoSuchAlgorithmException { SplitChange splitChangeToProcess = LocalhostSanitizer.sanitization(splitChange); // if the till is less than storage CN and different from the default till ignore the change if (splitChangeToProcess.till < changeNumber && splitChangeToProcess.till != -1) { diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 5827b1e1a..758cf39ac 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -31,8 +31,9 @@ import io.split.client.interceptors.GzipEncoderRequestInterceptor; import io.split.client.interceptors.SdkMetadataInterceptorFilter; import io.split.client.utils.FileInputStreamProvider; -import io.split.client.utils.InputStreamProvider; +import io.split.client.utils.FileTypeEnum; import io.split.client.utils.InputStreamProviderImp; +import io.split.client.utils.LocalhostPair; import io.split.client.utils.SDKMetadata; import io.split.engine.SDKReadinessGates; import io.split.engine.common.ConsumerSyncManager; @@ -102,6 +103,7 @@ import pluggable.CustomStorageWrapper; import java.io.IOException; +import java.io.InputStream; import java.net.InetAddress; import java.net.URI; import java.net.URISyntaxException; @@ -369,44 +371,19 @@ protected SplitFactoryImpl(SplitClientConfig config) { config.getThreadFactory()); // SplitFetcher + LocalhostPair pair = getInputStreamProviderAndFileType(config.splitFile(), config.inputStream(), config.fileType()); SplitChangeFetcher splitChangeFetcher = new LegacyLocalhostSplitChangeFetcher(config.splitFile()); - InputStreamProvider inputStreamProvider; - String splitFile = config.splitFile(); - if (splitFile != null) { - try { - if (splitFile.toLowerCase().endsWith(".json")) { - inputStreamProvider = new FileInputStreamProvider(splitFile); - splitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); - } else if (!splitFile.isEmpty() && (splitFile.endsWith(".yaml") || splitFile.endsWith(".yml"))) { - inputStreamProvider = new FileInputStreamProvider(splitFile); - splitChangeFetcher = new YamlLocalhostSplitChangeFetcher(inputStreamProvider); - } - } catch (Exception e) { - _log.warn(String.format("There was no file named %s found. " + - "We created a split client that returns default treatments for all feature flags for all of your users. " + - "If you wish to return a specific treatment for a feature flag, enter the name of that feature flag name and " + - "treatment name separated by whitespace in %s; one pair per line. Empty lines or lines starting with '#' are " + - "considered comments", - splitFile, splitFile), e); - } - } else if (config.inputStream() != null) { - inputStreamProvider = new InputStreamProviderImp(config.inputStream()); - if (config.fileType() != null) { - switch (config.fileType()) { - case JSON: - splitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); - break; - case YAML: - splitChangeFetcher = new YamlLocalhostSplitChangeFetcher(inputStreamProvider); - break; - } - } else { - _log.warn("Should add an fileType in the config if there is an inputStream"); - } + if (pair == null) { + _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."); } else { - _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile doesn't add it in the config."); + switch (pair.getFileTypeEnum()) { + case JSON: + splitChangeFetcher = new JsonLocalhostSplitChangeFetcher(pair.getInputStreamProvider()); + break; + case YAML: + splitChangeFetcher = new YamlLocalhostSplitChangeFetcher(pair.getInputStreamProvider()); + } } - SplitParser splitParser = new SplitParser(); _splitFetcher = new SplitFetcherImp(splitChangeFetcher, splitParser, splitCache, _telemetryStorageProducer); @@ -674,4 +651,39 @@ private UniqueKeysTracker createUniqueKeysTracker(SplitClientConfig config){ } return null; } + + private LocalhostPair getInputStreamProviderAndFileType(String splitFile, InputStream inputStream, + FileTypeEnum fileType) { + if (splitFile != null && inputStream != null) { + _log.warn("splitFile or inputStreamProvider should have a value, not both"); + return null; + } + if (inputStream != null && fileType == null) { + _log.warn("If inputStreamProvider is not null, then fileType must also have a non-null value"); + return null; + } + if (inputStream == null && splitFile == null){ + _log.warn("splitFile or inputStreamProvider should have a value"); + return null; + } + if (splitFile != null) { + try { + if (splitFile.toLowerCase().endsWith(".json")) { + return new LocalhostPair(new FileInputStreamProvider(splitFile), FileTypeEnum.JSON); + } else if (splitFile.endsWith(".yaml") || splitFile.endsWith(".yml")) { + return new LocalhostPair(new FileInputStreamProvider(splitFile), FileTypeEnum.YAML); + } + } catch (Exception e) { + _log.warn(String.format("There was no file named %s found. " + + "We created a split client that returns default treatments for all feature flags for all of your users. " + + "If you wish to return a specific treatment for a feature flag, enter the name of that feature flag name and " + + "treatment name separated by whitespace in %s; one pair per line. Empty lines or lines starting with '#' are " + + "considered comments", + splitFile, splitFile), e); + } + } else if (inputStream != null) { + return new LocalhostPair(new InputStreamProviderImp(inputStream), fileType); + } + return null; + } } \ No newline at end of file diff --git a/client/src/main/java/io/split/client/exceptions/InputStreamProviderException.java b/client/src/main/java/io/split/client/exceptions/InputStreamProviderException.java new file mode 100644 index 000000000..ca79b97e1 --- /dev/null +++ b/client/src/main/java/io/split/client/exceptions/InputStreamProviderException.java @@ -0,0 +1,14 @@ +package io.split.client.exceptions; + +public class InputStreamProviderException extends Exception { + private final String _fileName; + + public InputStreamProviderException(String fileName, String message) { + super(message); + _fileName = fileName; + } + + public String getFileName() { + return _fileName; + } +} \ No newline at end of file diff --git a/client/src/main/java/io/split/client/utils/FileInputStreamProvider.java b/client/src/main/java/io/split/client/utils/FileInputStreamProvider.java index a9ced73e7..81e15469c 100644 --- a/client/src/main/java/io/split/client/utils/FileInputStreamProvider.java +++ b/client/src/main/java/io/split/client/utils/FileInputStreamProvider.java @@ -1,5 +1,7 @@ package io.split.client.utils; +import io.split.client.exceptions.InputStreamProviderException; + import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; @@ -13,7 +15,11 @@ public FileInputStreamProvider(String fileName) { } @Override - public InputStream get() throws FileNotFoundException { - return new FileInputStream(_fileName); + public InputStream get() throws InputStreamProviderException { + try { + return new FileInputStream(_fileName); + } catch (FileNotFoundException f) { + throw new InputStreamProviderException(_fileName, f.getMessage()); + } } -} +} \ No newline at end of file diff --git a/client/src/main/java/io/split/client/utils/InputStreamProvider.java b/client/src/main/java/io/split/client/utils/InputStreamProvider.java index 8f23b50c8..02df28398 100644 --- a/client/src/main/java/io/split/client/utils/InputStreamProvider.java +++ b/client/src/main/java/io/split/client/utils/InputStreamProvider.java @@ -1,9 +1,10 @@ package io.split.client.utils; -import java.io.FileNotFoundException; +import io.split.client.exceptions.InputStreamProviderException; + import java.io.InputStream; public interface InputStreamProvider { - public InputStream get() throws FileNotFoundException; + InputStream get() throws InputStreamProviderException; } diff --git a/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java b/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java index 07ad240f4..c8e919cf4 100644 --- a/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java +++ b/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java @@ -1,6 +1,7 @@ package io.split.client.utils; -import java.io.FileNotFoundException; +import io.split.client.exceptions.InputStreamProviderException; + import java.io.InputStream; public class InputStreamProviderImp implements InputStreamProvider { @@ -11,7 +12,7 @@ public InputStreamProviderImp(InputStream inputStream){ } @Override - public InputStream get() throws FileNotFoundException { + public InputStream get() throws InputStreamProviderException { return _inputStream; } } \ No newline at end of file diff --git a/client/src/main/java/io/split/client/utils/LocalhostPair.java b/client/src/main/java/io/split/client/utils/LocalhostPair.java new file mode 100644 index 000000000..471aaced7 --- /dev/null +++ b/client/src/main/java/io/split/client/utils/LocalhostPair.java @@ -0,0 +1,20 @@ +package io.split.client.utils; + +public class LocalhostPair { + + private final InputStreamProvider _inputStreamProvider; + private final FileTypeEnum _fileTypeEnum; + + public LocalhostPair(InputStreamProvider inputStreamProvider, FileTypeEnum fileType) { + _inputStreamProvider = inputStreamProvider; + _fileTypeEnum = fileType; + } + + public InputStreamProvider getInputStreamProvider() { + return _inputStreamProvider; + } + + public FileTypeEnum getFileTypeEnum() { + return _fileTypeEnum; + } +} \ No newline at end of file diff --git a/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java index 57b6d320d..81ac81b13 100644 --- a/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java @@ -14,9 +14,7 @@ import org.yaml.snakeyaml.Yaml; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; import java.io.StringWriter; import java.util.ArrayList; import java.util.LinkedHashMap; From e9df6a6184be295191bb3b79e960a28694d7029f Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 31 Aug 2023 11:45:48 -0300 Subject: [PATCH 03/14] Add test cases --- .../JsonLocalhostSplitChangeFetcher.java | 6 ++-- .../io/split/client/SplitFactoryImpl.java | 10 ++++-- .../io/split/client/SplitFactoryImplTest.java | 36 +++++++++++++++++-- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java b/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java index 41ca8f06b..ae62e5739 100644 --- a/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java @@ -1,5 +1,6 @@ package io.split.client; +import com.google.common.base.Charsets; import com.google.gson.stream.JsonReader; import io.split.client.dtos.SplitChange; import io.split.client.exceptions.InputStreamProviderException; @@ -31,12 +32,13 @@ public JsonLocalhostSplitChangeFetcher(InputStreamProvider inputStreamProvider) @Override public SplitChange fetch(long since, FetchOptions options) { try { - JsonReader jsonReader = new JsonReader(new BufferedReader(new InputStreamReader(_inputStreamProvider.get(), "UTF-8"))); + JsonReader jsonReader = new JsonReader(new BufferedReader(new InputStreamReader(_inputStreamProvider.get(), Charsets.UTF_8))); SplitChange splitChange = Json.fromJson(jsonReader, SplitChange.class); return processSplitChange(splitChange, since); } catch (InputStreamProviderException i) { _log.warn(String.format("Problem to fetch split change using file named %s", i.getFileName())); - throw new IllegalStateException("Problem fetching splitChanges: " + i.getMessage(), i); + throw new IllegalStateException(String.format("Problem fetching splitChanges using file named %s: %s", + i.getFileName(), i.getMessage()), i); } catch (Exception e) { _log.warn(String.format("Problem to fetch split change using a file"), e); throw new IllegalStateException("Problem fetching splitChanges: " + e.getMessage(), e); diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 758cf39ac..d28964d6a 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -372,8 +372,9 @@ protected SplitFactoryImpl(SplitClientConfig config) { // SplitFetcher LocalhostPair pair = getInputStreamProviderAndFileType(config.splitFile(), config.inputStream(), config.fileType()); - SplitChangeFetcher splitChangeFetcher = new LegacyLocalhostSplitChangeFetcher(config.splitFile()); + SplitChangeFetcher splitChangeFetcher; if (pair == null) { + splitChangeFetcher = new LegacyLocalhostSplitChangeFetcher(config.splitFile()); _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."); } else { switch (pair.getFileTypeEnum()) { @@ -382,6 +383,9 @@ protected SplitFactoryImpl(SplitClientConfig config) { break; case YAML: splitChangeFetcher = new YamlLocalhostSplitChangeFetcher(pair.getInputStreamProvider()); + break; + default: + splitChangeFetcher = new LegacyLocalhostSplitChangeFetcher(config.splitFile()); } } SplitParser splitParser = new SplitParser(); @@ -652,7 +656,7 @@ private UniqueKeysTracker createUniqueKeysTracker(SplitClientConfig config){ return null; } - private LocalhostPair getInputStreamProviderAndFileType(String splitFile, InputStream inputStream, + LocalhostPair getInputStreamProviderAndFileType(String splitFile, InputStream inputStream, FileTypeEnum fileType) { if (splitFile != null && inputStream != null) { _log.warn("splitFile or inputStreamProvider should have a value, not both"); @@ -681,7 +685,7 @@ private LocalhostPair getInputStreamProviderAndFileType(String splitFile, InputS "considered comments", splitFile, splitFile), e); } - } else if (inputStream != null) { + } else { return new LocalhostPair(new InputStreamProviderImp(inputStream), fileType); } return null; diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index ad2334d39..f280a6673 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -1,19 +1,27 @@ package io.split.client; import io.split.client.impressions.ImpressionsManager; +import io.split.client.utils.FileInputStreamProvider; +import io.split.client.utils.FileTypeEnum; +import io.split.client.utils.LocalhostPair; import io.split.integrations.IntegrationsConfig; import io.split.storages.enums.OperationMode; import io.split.storages.pluggable.domain.UserStorageWrapper; import io.split.telemetry.storage.TelemetryStorage; import io.split.telemetry.synchronizer.TelemetrySynchronizer; import junit.framework.TestCase; +import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import pluggable.CustomStorageWrapper; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.net.URISyntaxException; +import java.util.zip.InflaterInputStream; public class SplitFactoryImplTest extends TestCase { public static final String API_KEY ="29013ionasdasd09u"; @@ -162,8 +170,6 @@ public void testFactoryConsumerInstantiation() throws Exception { Mockito.verify(telemetrySynchronizer, Mockito.times(1)).synchronizeConfig(Mockito.anyObject(), Mockito.anyLong(), Mockito.anyObject(), Mockito.anyObject()); } - - @Test public void testFactoryConsumerInstantiationRetryReadiness() throws Exception { CustomStorageWrapper customStorageWrapper = Mockito.mock(CustomStorageWrapper.class); @@ -221,4 +227,30 @@ public void testFactoryConsumerDestroy() throws NoSuchFieldException, URISyntaxE assertTrue(splitFactory.isDestroyed()); Mockito.verify(userStorageWrapper, Mockito.times(1)).disconnect(); } + + @Test + public void testGetInputStreamProviderAndFileType() throws URISyntaxException, FileNotFoundException { + SplitClientConfig splitClientConfig = SplitClientConfig.builder() + .setBlockUntilReadyTimeout(10000) + .build(); + SplitFactoryImpl splitFactory = new SplitFactoryImpl("localhost", splitClientConfig); + //splitFile null and InputStream null + Assert.assertNull(splitFactory.getInputStreamProviderAndFileType(null, null, FileTypeEnum.JSON)); + + //splitFile not null and InputStream not null + InputStream inputStream = new FileInputStream("src/test/resources/split_init.json"); + Assert.assertNull(splitFactory.getInputStreamProviderAndFileType("test", inputStream, FileTypeEnum.JSON)); + + //inputStream is not null and fileType is null + Assert.assertNull(splitFactory.getInputStreamProviderAndFileType(null, inputStream, null)); + + //split file not null + LocalhostPair localhostPair = splitFactory.getInputStreamProviderAndFileType("src/test/resources/split_init.json", + null, null); + Assert.assertNotNull(localhostPair); + + //inputStream is not null and filetype is not null + localhostPair = splitFactory.getInputStreamProviderAndFileType(null, inputStream, FileTypeEnum.JSON); + Assert.assertNotNull(localhostPair); + } } From eaa1609fa24cf3b2972a9bd62fe6fa7847a8569c Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 31 Aug 2023 15:23:06 -0300 Subject: [PATCH 04/14] Add test cases for InputStream and localhost --- .../client/JsonLocalhostSplitChangeFetcher.java | 6 ++---- .../client/YamlLocalhostSplitChangeFetcher.java | 5 ++++- .../client/JsonLocalhostSplitChangeFetcherTest.java | 9 +++++++++ .../java/io/split/client/SplitFactoryImplTest.java | 4 +--- .../client/YamlLocalhostSplitChangeFetcherTest.java | 9 +++++++++ .../client/utils/FileInputStreamProviderTest.java | 13 +++++++++++++ 6 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 client/src/test/java/io/split/client/utils/FileInputStreamProviderTest.java diff --git a/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java b/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java index ae62e5739..0917d3591 100644 --- a/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java @@ -1,6 +1,5 @@ package io.split.client; -import com.google.common.base.Charsets; import com.google.gson.stream.JsonReader; import io.split.client.dtos.SplitChange; import io.split.client.exceptions.InputStreamProviderException; @@ -14,6 +13,7 @@ import java.io.BufferedReader; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; @@ -32,15 +32,13 @@ public JsonLocalhostSplitChangeFetcher(InputStreamProvider inputStreamProvider) @Override public SplitChange fetch(long since, FetchOptions options) { try { - JsonReader jsonReader = new JsonReader(new BufferedReader(new InputStreamReader(_inputStreamProvider.get(), Charsets.UTF_8))); + JsonReader jsonReader = new JsonReader(new BufferedReader(new InputStreamReader(_inputStreamProvider.get(), StandardCharsets.UTF_8))); SplitChange splitChange = Json.fromJson(jsonReader, SplitChange.class); return processSplitChange(splitChange, since); } catch (InputStreamProviderException i) { - _log.warn(String.format("Problem to fetch split change using file named %s", i.getFileName())); throw new IllegalStateException(String.format("Problem fetching splitChanges using file named %s: %s", i.getFileName(), i.getMessage()), i); } catch (Exception e) { - _log.warn(String.format("Problem to fetch split change using a file"), e); throw new IllegalStateException("Problem fetching splitChanges: " + e.getMessage(), e); } } diff --git a/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java b/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java index 44c47c9dc..37e78eb03 100644 --- a/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java @@ -5,6 +5,7 @@ import io.split.client.dtos.Split; import io.split.client.dtos.SplitChange; import io.split.client.dtos.Status; +import io.split.client.exceptions.InputStreamProviderException; import io.split.client.utils.InputStreamProvider; import io.split.client.utils.LocalhostConstants; import io.split.engine.common.FetchOptions; @@ -22,7 +23,6 @@ import static io.split.client.utils.LocalhostSanitizer.createCondition; - public class YamlLocalhostSplitChangeFetcher implements SplitChangeFetcher { private static final Logger _log = LoggerFactory.getLogger(YamlLocalhostSplitChangeFetcher.class); @@ -75,6 +75,9 @@ public SplitChange fetch(long since, FetchOptions options) { splitChange.till = since; splitChange.since = since; return splitChange; + } catch (InputStreamProviderException i) { + throw new IllegalStateException(String.format("Problem fetching splitChanges using file named %s: %s", + i.getFileName(), i.getMessage()), i); } catch (Exception e) { _log.warn(String.format("Problem to fetch split change using a file"), e); throw new IllegalStateException("Problem fetching splitChanges: " + e.getMessage(), e); diff --git a/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java index ccca3b7bd..e9a3c5cdd 100644 --- a/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java @@ -169,4 +169,13 @@ public void testSplitChangeSplitsDifferentScenarios() throws IOException { Assert.assertEquals(2323, splitChange.till); Assert.assertEquals(2323, splitChange.since); } + + @Test(expected = IllegalStateException.class) + public void processTestForException() { + InputStreamProvider inputStreamProvider = new FileInputStreamProvider("src/test/resources/notExist.json"); + JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); + FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); + + SplitChange splitChange = localhostSplitChangeFetcher.fetch(-1L, fetchOptions); + } } \ No newline at end of file diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index f280a6673..06214b015 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -1,7 +1,6 @@ package io.split.client; import io.split.client.impressions.ImpressionsManager; -import io.split.client.utils.FileInputStreamProvider; import io.split.client.utils.FileTypeEnum; import io.split.client.utils.LocalhostPair; import io.split.integrations.IntegrationsConfig; @@ -21,7 +20,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.net.URISyntaxException; -import java.util.zip.InflaterInputStream; public class SplitFactoryImplTest extends TestCase { public static final String API_KEY ="29013ionasdasd09u"; @@ -253,4 +251,4 @@ public void testGetInputStreamProviderAndFileType() throws URISyntaxException, F localhostPair = splitFactory.getInputStreamProviderAndFileType(null, inputStream, FileTypeEnum.JSON); Assert.assertNotNull(localhostPair); } -} +} \ No newline at end of file diff --git a/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java index 81ac81b13..dabd96781 100644 --- a/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java @@ -74,4 +74,13 @@ public void testParseSplitChange() throws IOException { Assert.assertEquals("control", split.defaultTreatment); } } + + @Test(expected = IllegalStateException.class) + public void processTestForException() { + InputStreamProvider inputStreamProvider = new FileInputStreamProvider("src/test/resources/notExist.yaml"); + YamlLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new YamlLocalhostSplitChangeFetcher(inputStreamProvider); + FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); + + SplitChange splitChange = localhostSplitChangeFetcher.fetch(-1L, fetchOptions); + } } \ No newline at end of file diff --git a/client/src/test/java/io/split/client/utils/FileInputStreamProviderTest.java b/client/src/test/java/io/split/client/utils/FileInputStreamProviderTest.java new file mode 100644 index 000000000..5c9e34d2d --- /dev/null +++ b/client/src/test/java/io/split/client/utils/FileInputStreamProviderTest.java @@ -0,0 +1,13 @@ +package io.split.client.utils; + +import io.split.client.exceptions.InputStreamProviderException; +import org.junit.Test; + +public class FileInputStreamProviderTest { + + @Test(expected = InputStreamProviderException.class) + public void processTestForException() throws InputStreamProviderException { + FileInputStreamProvider fileInputStreamProvider = new FileInputStreamProvider("src/test/resources/notExist.json"); + fileInputStreamProvider.get(); + } +} \ No newline at end of file From 6806d919a78b931f15628ecb9e1cb026360252bc Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 31 Aug 2023 15:41:27 -0300 Subject: [PATCH 05/14] Remove a extra log --- .../java/io/split/client/YamlLocalhostSplitChangeFetcher.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java b/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java index 37e78eb03..68852de47 100644 --- a/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java @@ -79,8 +79,7 @@ public SplitChange fetch(long since, FetchOptions options) { throw new IllegalStateException(String.format("Problem fetching splitChanges using file named %s: %s", i.getFileName(), i.getMessage()), i); } catch (Exception e) { - _log.warn(String.format("Problem to fetch split change using a file"), e); - throw new IllegalStateException("Problem fetching splitChanges: " + e.getMessage(), e); + throw new IllegalStateException("Problem fetching splitChanges using a yaml file: " + e.getMessage(), e); } } } \ No newline at end of file From bd15faa66d4c82a13a8735833aceae62ba1a133d Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 1 Sep 2023 11:40:45 -0300 Subject: [PATCH 06/14] [7445] PR suggestions --- .../JsonLocalhostSplitChangeFetcher.java | 5 +- .../io/split/client/SplitFactoryImpl.java | 51 ++++---- .../YamlLocalhostSplitChangeFetcher.java | 5 +- .../InputStreamProviderException.java | 8 +- .../client/utils/FileInputStreamProvider.java | 3 +- .../client/utils/InputStreamProviderImp.java | 2 +- .../io/split/client/utils/LocalhostPair.java | 20 --- .../experiments/SplitChangeFetcher.java | 3 +- .../engine/experiments/SplitFetcherImp.java | 3 +- .../JsonLocalhostSplitChangeFetcherTest.java | 17 +-- .../io/split/client/SplitFactoryImplTest.java | 123 +++++++++++++++--- .../YamlLocalhostSplitChangeFetcherTest.java | 7 +- .../common/LocalhostSynchronizerTest.java | 9 +- .../engine/experiments/SplitFetcherTest.java | 5 +- .../SplitSynchronizationTaskTest.java | 3 +- 15 files changed, 166 insertions(+), 98 deletions(-) delete mode 100644 client/src/main/java/io/split/client/utils/LocalhostPair.java diff --git a/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java b/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java index 0917d3591..cf91712d3 100644 --- a/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java @@ -30,14 +30,13 @@ public JsonLocalhostSplitChangeFetcher(InputStreamProvider inputStreamProvider) } @Override - public SplitChange fetch(long since, FetchOptions options) { + public SplitChange fetch(long since, FetchOptions options) throws InputStreamProviderException { try { JsonReader jsonReader = new JsonReader(new BufferedReader(new InputStreamReader(_inputStreamProvider.get(), StandardCharsets.UTF_8))); SplitChange splitChange = Json.fromJson(jsonReader, SplitChange.class); return processSplitChange(splitChange, since); } catch (InputStreamProviderException i) { - throw new IllegalStateException(String.format("Problem fetching splitChanges using file named %s: %s", - i.getFileName(), i.getMessage()), i); + throw i; } catch (Exception e) { throw new IllegalStateException("Problem fetching splitChanges: " + e.getMessage(), e); } diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index d28964d6a..80f4df244 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -33,7 +33,6 @@ import io.split.client.utils.FileInputStreamProvider; import io.split.client.utils.FileTypeEnum; import io.split.client.utils.InputStreamProviderImp; -import io.split.client.utils.LocalhostPair; import io.split.client.utils.SDKMetadata; import io.split.engine.SDKReadinessGates; import io.split.engine.common.ConsumerSyncManager; @@ -371,23 +370,7 @@ protected SplitFactoryImpl(SplitClientConfig config) { config.getThreadFactory()); // SplitFetcher - LocalhostPair pair = getInputStreamProviderAndFileType(config.splitFile(), config.inputStream(), config.fileType()); - SplitChangeFetcher splitChangeFetcher; - if (pair == null) { - splitChangeFetcher = new LegacyLocalhostSplitChangeFetcher(config.splitFile()); - _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."); - } else { - switch (pair.getFileTypeEnum()) { - case JSON: - splitChangeFetcher = new JsonLocalhostSplitChangeFetcher(pair.getInputStreamProvider()); - break; - case YAML: - splitChangeFetcher = new YamlLocalhostSplitChangeFetcher(pair.getInputStreamProvider()); - break; - default: - splitChangeFetcher = new LegacyLocalhostSplitChangeFetcher(config.splitFile()); - } - } + SplitChangeFetcher splitChangeFetcher = createSplitChangeFetcher(config); SplitParser splitParser = new SplitParser(); _splitFetcher = new SplitFetcherImp(splitChangeFetcher, splitParser, splitCache, _telemetryStorageProducer); @@ -656,26 +639,31 @@ private UniqueKeysTracker createUniqueKeysTracker(SplitClientConfig config){ return null; } - LocalhostPair getInputStreamProviderAndFileType(String splitFile, InputStream inputStream, - FileTypeEnum fileType) { + private SplitChangeFetcher createSplitChangeFetcher(SplitClientConfig splitClientConfig) { + String splitFile = splitClientConfig.splitFile(); + InputStream inputStream = splitClientConfig.inputStream(); + FileTypeEnum fileType = splitClientConfig.fileType(); if (splitFile != null && inputStream != null) { _log.warn("splitFile or inputStreamProvider should have a value, not both"); - return null; + _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."); + return new LegacyLocalhostSplitChangeFetcher(splitFile); } if (inputStream != null && fileType == null) { _log.warn("If inputStreamProvider is not null, then fileType must also have a non-null value"); - return null; + _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."); + return new LegacyLocalhostSplitChangeFetcher(splitFile); } if (inputStream == null && splitFile == null){ _log.warn("splitFile or inputStreamProvider should have a value"); - return null; + _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."); + return new LegacyLocalhostSplitChangeFetcher(splitFile); } if (splitFile != null) { try { if (splitFile.toLowerCase().endsWith(".json")) { - return new LocalhostPair(new FileInputStreamProvider(splitFile), FileTypeEnum.JSON); + return new JsonLocalhostSplitChangeFetcher(new FileInputStreamProvider(splitFile)); } else if (splitFile.endsWith(".yaml") || splitFile.endsWith(".yml")) { - return new LocalhostPair(new FileInputStreamProvider(splitFile), FileTypeEnum.YAML); + return new YamlLocalhostSplitChangeFetcher(new FileInputStreamProvider(splitFile)); } } catch (Exception e) { _log.warn(String.format("There was no file named %s found. " + @@ -686,8 +674,17 @@ LocalhostPair getInputStreamProviderAndFileType(String splitFile, InputStream in splitFile, splitFile), e); } } else { - return new LocalhostPair(new InputStreamProviderImp(inputStream), fileType); + switch (fileType) { + case JSON: + return new JsonLocalhostSplitChangeFetcher(new InputStreamProviderImp(inputStream)); + case YAML: + return new YamlLocalhostSplitChangeFetcher(new InputStreamProviderImp(inputStream)); + default: + _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."); + return new LegacyLocalhostSplitChangeFetcher(splitFile); + } } - return null; + _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."); + return new LegacyLocalhostSplitChangeFetcher(splitFile); } } \ No newline at end of file diff --git a/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java b/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java index 68852de47..5d5a87c2f 100644 --- a/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java @@ -33,7 +33,7 @@ public YamlLocalhostSplitChangeFetcher(InputStreamProvider inputStreamProvider) } @Override - public SplitChange fetch(long since, FetchOptions options) { + public SplitChange fetch(long since, FetchOptions options) throws InputStreamProviderException { try { Yaml yaml = new Yaml(); List>> yamlSplits = yaml.load(_inputStreamProvider.get()); @@ -76,8 +76,7 @@ public SplitChange fetch(long since, FetchOptions options) { splitChange.since = since; return splitChange; } catch (InputStreamProviderException i) { - throw new IllegalStateException(String.format("Problem fetching splitChanges using file named %s: %s", - i.getFileName(), i.getMessage()), i); + throw i; } catch (Exception e) { throw new IllegalStateException("Problem fetching splitChanges using a yaml file: " + e.getMessage(), e); } diff --git a/client/src/main/java/io/split/client/exceptions/InputStreamProviderException.java b/client/src/main/java/io/split/client/exceptions/InputStreamProviderException.java index ca79b97e1..33fba556f 100644 --- a/client/src/main/java/io/split/client/exceptions/InputStreamProviderException.java +++ b/client/src/main/java/io/split/client/exceptions/InputStreamProviderException.java @@ -1,14 +1,8 @@ package io.split.client.exceptions; public class InputStreamProviderException extends Exception { - private final String _fileName; - public InputStreamProviderException(String fileName, String message) { + public InputStreamProviderException(String message) { super(message); - _fileName = fileName; - } - - public String getFileName() { - return _fileName; } } \ No newline at end of file diff --git a/client/src/main/java/io/split/client/utils/FileInputStreamProvider.java b/client/src/main/java/io/split/client/utils/FileInputStreamProvider.java index 81e15469c..c1d9f9812 100644 --- a/client/src/main/java/io/split/client/utils/FileInputStreamProvider.java +++ b/client/src/main/java/io/split/client/utils/FileInputStreamProvider.java @@ -19,7 +19,8 @@ public InputStream get() throws InputStreamProviderException { try { return new FileInputStream(_fileName); } catch (FileNotFoundException f) { - throw new InputStreamProviderException(_fileName, f.getMessage()); + throw new InputStreamProviderException(String.format("Problem fetching splitChanges using file named %s: %s", + _fileName, f.getMessage())); } } } \ No newline at end of file diff --git a/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java b/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java index c8e919cf4..4b945fcd3 100644 --- a/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java +++ b/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java @@ -5,7 +5,7 @@ import java.io.InputStream; public class InputStreamProviderImp implements InputStreamProvider { - private InputStream _inputStream; + private final InputStream _inputStream; public InputStreamProviderImp(InputStream inputStream){ _inputStream = inputStream; diff --git a/client/src/main/java/io/split/client/utils/LocalhostPair.java b/client/src/main/java/io/split/client/utils/LocalhostPair.java deleted file mode 100644 index 471aaced7..000000000 --- a/client/src/main/java/io/split/client/utils/LocalhostPair.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.split.client.utils; - -public class LocalhostPair { - - private final InputStreamProvider _inputStreamProvider; - private final FileTypeEnum _fileTypeEnum; - - public LocalhostPair(InputStreamProvider inputStreamProvider, FileTypeEnum fileType) { - _inputStreamProvider = inputStreamProvider; - _fileTypeEnum = fileType; - } - - public InputStreamProvider getInputStreamProvider() { - return _inputStreamProvider; - } - - public FileTypeEnum getFileTypeEnum() { - return _fileTypeEnum; - } -} \ No newline at end of file diff --git a/client/src/main/java/io/split/engine/experiments/SplitChangeFetcher.java b/client/src/main/java/io/split/engine/experiments/SplitChangeFetcher.java index 7c5fbe76e..c27fca1df 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitChangeFetcher.java +++ b/client/src/main/java/io/split/engine/experiments/SplitChangeFetcher.java @@ -1,6 +1,7 @@ package io.split.engine.experiments; import io.split.client.dtos.SplitChange; +import io.split.client.exceptions.InputStreamProviderException; import io.split.engine.common.FetchOptions; /** @@ -32,5 +33,5 @@ public interface SplitChangeFetcher { * @return SegmentChange * @throws java.lang.RuntimeException if there was a problem computing split changes */ - SplitChange fetch(long since, FetchOptions options); + SplitChange fetch(long since, FetchOptions options) throws InputStreamProviderException; } diff --git a/client/src/main/java/io/split/engine/experiments/SplitFetcherImp.java b/client/src/main/java/io/split/engine/experiments/SplitFetcherImp.java index 1043ccfcf..a94c07735 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitFetcherImp.java +++ b/client/src/main/java/io/split/engine/experiments/SplitFetcherImp.java @@ -1,6 +1,7 @@ package io.split.engine.experiments; import io.split.client.dtos.SplitChange; +import io.split.client.exceptions.InputStreamProviderException; import io.split.client.utils.FeatureFlagsToUpdate; import io.split.storages.SplitCacheProducer; import io.split.telemetry.domain.enums.LastSynchronizationRecordsEnum; @@ -89,7 +90,7 @@ public void run() { this.forceRefresh(new FetchOptions.Builder().cacheControlHeaders(false).build()); } - private Set runWithoutExceptionHandling(FetchOptions options) throws InterruptedException { + private Set runWithoutExceptionHandling(FetchOptions options) throws InterruptedException, InputStreamProviderException { SplitChange change = _splitChangeFetcher.fetch(_splitCacheProducer.getChangeNumber(), options); Set segments = new HashSet<>(); diff --git a/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java index e9a3c5cdd..9a9e4519e 100644 --- a/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java @@ -4,6 +4,7 @@ import io.split.client.dtos.Split; import io.split.client.dtos.SplitChange; import io.split.client.dtos.Status; +import io.split.client.exceptions.InputStreamProviderException; import io.split.client.utils.FileInputStreamProvider; import io.split.client.utils.InputStreamProvider; import io.split.client.utils.InputStreamProviderImp; @@ -33,7 +34,7 @@ public class JsonLocalhostSplitChangeFetcherTest { private String TEST_4 = "{\"splits\":[{\"trafficTypeName\":\"user\",\"name\":\"SPLIT_1\",\"trafficAllocation\":100,\"trafficAllocationSeed\":-1780071202,\"seed\":-1442762199,\"status\":\"ACTIVE\",\"killed\":false,\"defaultTreatment\":\"off\",\"changeNumber\":1675443537882,\"algo\":2,\"configurations\":{},\"conditions\":[{\"conditionType\":\"ROLLOUT\",\"matcherGroup\":{\"combiner\":\"AND\",\"matchers\":[{\"keySelector\":{\"trafficType\":\"user\",\"attribute\":null},\"matcherType\":\"ALL_KEYS\",\"negate\":false,\"userDefinedSegmentMatcherData\":null,\"whitelistMatcherData\":null,\"unaryNumericMatcherData\":null,\"betweenMatcherData\":null,\"booleanMatcherData\":null,\"dependencyMatcherData\":null,\"stringMatcherData\":null}]},\"partitions\":[{\"treatment\":\"on\",\"size\":0},{\"treatment\":\"off\",\"size\":100}],\"label\":\"default rule\"}]}],\"since\":-1,\"till\":445345}"; private String TEST_5 = "{\"splits\":[{\"trafficTypeName\":\"user\",\"name\":\"SPLIT_1\",\"trafficAllocation\":100,\"trafficAllocationSeed\":-1780071202,\"seed\":-1442762199,\"status\":\"ACTIVE\",\"killed\":false,\"defaultTreatment\":\"off\",\"changeNumber\":1675443537882,\"algo\":2,\"configurations\":{},\"conditions\":[{\"conditionType\":\"ROLLOUT\",\"matcherGroup\":{\"combiner\":\"AND\",\"matchers\":[{\"keySelector\":{\"trafficType\":\"user\",\"attribute\":null},\"matcherType\":\"ALL_KEYS\",\"negate\":false,\"userDefinedSegmentMatcherData\":null,\"whitelistMatcherData\":null,\"unaryNumericMatcherData\":null,\"betweenMatcherData\":null,\"booleanMatcherData\":null,\"dependencyMatcherData\":null,\"stringMatcherData\":null}]},\"partitions\":[{\"treatment\":\"on\",\"size\":0},{\"treatment\":\"off\",\"size\":100}],\"label\":\"default rule\"}]},{\"trafficTypeName\":\"user\",\"name\":\"SPLIT_2\",\"trafficAllocation\":100,\"trafficAllocationSeed\":-1780071202,\"seed\":-1442762199,\"status\":\"ACTIVE\",\"killed\":false,\"defaultTreatment\":\"off\",\"changeNumber\":1675443537882,\"algo\":2,\"configurations\":{},\"conditions\":[{\"conditionType\":\"ROLLOUT\",\"matcherGroup\":{\"combiner\":\"AND\",\"matchers\":[{\"keySelector\":{\"trafficType\":\"user\",\"attribute\":null},\"matcherType\":\"ALL_KEYS\",\"negate\":false,\"userDefinedSegmentMatcherData\":null,\"whitelistMatcherData\":null,\"unaryNumericMatcherData\":null,\"betweenMatcherData\":null,\"booleanMatcherData\":null,\"dependencyMatcherData\":null,\"stringMatcherData\":null}]},\"partitions\":[{\"treatment\":\"on\",\"size\":0},{\"treatment\":\"off\",\"size\":100}],\"label\":\"default rule\"}]}],\"since\":-1,\"till\":-1}"; @Test - public void testParseSplitChange() throws FileNotFoundException { + public void testParseSplitChange() throws FileNotFoundException, InputStreamProviderException { InputStream inputStream = new FileInputStream("src/test/resources/split_init.json"); InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); @@ -48,7 +49,7 @@ public void testParseSplitChange() throws FileNotFoundException { } @Test - public void testSinceAndTillSanitization() throws FileNotFoundException { + public void testSinceAndTillSanitization() throws FileNotFoundException, InputStreamProviderException { InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangeTillSanitization.json"); InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); @@ -61,7 +62,7 @@ public void testSinceAndTillSanitization() throws FileNotFoundException { } @Test - public void testSplitChangeWithoutSplits() throws FileNotFoundException { + public void testSplitChangeWithoutSplits() throws FileNotFoundException, InputStreamProviderException { InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangeWithoutSplits.json"); InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); @@ -73,7 +74,7 @@ public void testSplitChangeWithoutSplits() throws FileNotFoundException { } @Test - public void testSplitChangeSplitsToSanitize() throws FileNotFoundException { + public void testSplitChangeSplitsToSanitize() throws FileNotFoundException, InputStreamProviderException { InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangeSplitsToSanitize.json"); InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); @@ -90,7 +91,7 @@ public void testSplitChangeSplitsToSanitize() throws FileNotFoundException { } @Test - public void testSplitChangeSplitsToSanitizeMatchersNull() throws FileNotFoundException { + public void testSplitChangeSplitsToSanitizeMatchersNull() throws FileNotFoundException, InputStreamProviderException { InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangerMatchersNull.json"); InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); @@ -107,7 +108,7 @@ public void testSplitChangeSplitsToSanitizeMatchersNull() throws FileNotFoundExc } @Test - public void testSplitChangeSplitsDifferentScenarios() throws IOException { + public void testSplitChangeSplitsDifferentScenarios() throws IOException, InputStreamProviderException { File file = folder.newFile("test_0.json"); @@ -170,8 +171,8 @@ public void testSplitChangeSplitsDifferentScenarios() throws IOException { Assert.assertEquals(2323, splitChange.since); } - @Test(expected = IllegalStateException.class) - public void processTestForException() { + @Test(expected = InputStreamProviderException.class) + public void processTestForException() throws InputStreamProviderException { InputStreamProvider inputStreamProvider = new FileInputStreamProvider("src/test/resources/notExist.json"); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); diff --git a/client/src/test/java/io/split/client/SplitFactoryImplTest.java b/client/src/test/java/io/split/client/SplitFactoryImplTest.java index 06214b015..f51ccae36 100644 --- a/client/src/test/java/io/split/client/SplitFactoryImplTest.java +++ b/client/src/test/java/io/split/client/SplitFactoryImplTest.java @@ -2,7 +2,6 @@ import io.split.client.impressions.ImpressionsManager; import io.split.client.utils.FileTypeEnum; -import io.split.client.utils.LocalhostPair; import io.split.integrations.IntegrationsConfig; import io.split.storages.enums.OperationMode; import io.split.storages.pluggable.domain.UserStorageWrapper; @@ -18,6 +17,8 @@ import java.io.FileNotFoundException; import java.io.InputStream; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.net.URISyntaxException; @@ -227,28 +228,120 @@ public void testFactoryConsumerDestroy() throws NoSuchFieldException, URISyntaxE } @Test - public void testGetInputStreamProviderAndFileType() throws URISyntaxException, FileNotFoundException { + public void testLocalhostLegacy() throws URISyntaxException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { SplitClientConfig splitClientConfig = SplitClientConfig.builder() .setBlockUntilReadyTimeout(10000) .build(); SplitFactoryImpl splitFactory = new SplitFactoryImpl("localhost", splitClientConfig); - //splitFile null and InputStream null - Assert.assertNull(splitFactory.getInputStreamProviderAndFileType(null, null, FileTypeEnum.JSON)); - //splitFile not null and InputStream not null + Method method = SplitFactoryImpl.class.getDeclaredMethod("createSplitChangeFetcher", SplitClientConfig.class); + method.setAccessible(true); + Object splitChangeFetcher = method.invoke(splitFactory, splitClientConfig); + Assert.assertTrue(splitChangeFetcher instanceof LegacyLocalhostSplitChangeFetcher); + } + + @Test + public void testLocalhostYaml() throws URISyntaxException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { + SplitClientConfig splitClientConfig = SplitClientConfig.builder() + .splitFile("src/test/resources/split.yaml") + .setBlockUntilReadyTimeout(10000) + .build(); + SplitFactoryImpl splitFactory = new SplitFactoryImpl("localhost", splitClientConfig); + + Method method = SplitFactoryImpl.class.getDeclaredMethod("createSplitChangeFetcher", SplitClientConfig.class); + method.setAccessible(true); + Object splitChangeFetcher = method.invoke(splitFactory, splitClientConfig); + Assert.assertTrue(splitChangeFetcher instanceof YamlLocalhostSplitChangeFetcher); + } + + @Test + public void testLocalhosJson() throws URISyntaxException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { + SplitClientConfig splitClientConfig = SplitClientConfig.builder() + .splitFile("src/test/resources/split_init.json") + .setBlockUntilReadyTimeout(10000) + .build(); + SplitFactoryImpl splitFactory = new SplitFactoryImpl("localhost", splitClientConfig); + + Method method = SplitFactoryImpl.class.getDeclaredMethod("createSplitChangeFetcher", SplitClientConfig.class); + method.setAccessible(true); + Object splitChangeFetcher = method.invoke(splitFactory, splitClientConfig); + Assert.assertTrue(splitChangeFetcher instanceof JsonLocalhostSplitChangeFetcher); + } + + @Test + public void testLocalhosYamlInputStream() throws URISyntaxException, NoSuchMethodException, InvocationTargetException, + IllegalAccessException, FileNotFoundException { + InputStream inputStream = new FileInputStream("src/test/resources/split.yaml"); + SplitClientConfig splitClientConfig = SplitClientConfig.builder() + .splitFile(inputStream, FileTypeEnum.YAML) + .setBlockUntilReadyTimeout(10000) + .build(); + SplitFactoryImpl splitFactory = new SplitFactoryImpl("localhost", splitClientConfig); + + Method method = SplitFactoryImpl.class.getDeclaredMethod("createSplitChangeFetcher", SplitClientConfig.class); + method.setAccessible(true); + Object splitChangeFetcher = method.invoke(splitFactory, splitClientConfig); + Assert.assertTrue(splitChangeFetcher instanceof YamlLocalhostSplitChangeFetcher); + } + + @Test + public void testLocalhosJsonInputStream() throws URISyntaxException, NoSuchMethodException, InvocationTargetException, + IllegalAccessException, FileNotFoundException { InputStream inputStream = new FileInputStream("src/test/resources/split_init.json"); - Assert.assertNull(splitFactory.getInputStreamProviderAndFileType("test", inputStream, FileTypeEnum.JSON)); + SplitClientConfig splitClientConfig = SplitClientConfig.builder() + .splitFile(inputStream, FileTypeEnum.JSON) + .setBlockUntilReadyTimeout(10000) + .build(); + SplitFactoryImpl splitFactory = new SplitFactoryImpl("localhost", splitClientConfig); + + Method method = SplitFactoryImpl.class.getDeclaredMethod("createSplitChangeFetcher", SplitClientConfig.class); + method.setAccessible(true); + Object splitChangeFetcher = method.invoke(splitFactory, splitClientConfig); + Assert.assertTrue(splitChangeFetcher instanceof JsonLocalhostSplitChangeFetcher); + } + + @Test + public void testLocalhosJsonInputStreamNull() throws URISyntaxException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { + SplitClientConfig splitClientConfig = SplitClientConfig.builder() + .splitFile(null, FileTypeEnum.JSON) + .setBlockUntilReadyTimeout(10000) + .build(); + SplitFactoryImpl splitFactory = new SplitFactoryImpl("localhost", splitClientConfig); - //inputStream is not null and fileType is null - Assert.assertNull(splitFactory.getInputStreamProviderAndFileType(null, inputStream, null)); + Method method = SplitFactoryImpl.class.getDeclaredMethod("createSplitChangeFetcher", SplitClientConfig.class); + method.setAccessible(true); + Object splitChangeFetcher = method.invoke(splitFactory, splitClientConfig); + Assert.assertTrue(splitChangeFetcher instanceof LegacyLocalhostSplitChangeFetcher); + } - //split file not null - LocalhostPair localhostPair = splitFactory.getInputStreamProviderAndFileType("src/test/resources/split_init.json", - null, null); - Assert.assertNotNull(localhostPair); + @Test + public void testLocalhosJsonInputStreamAndFileTypeNull() throws URISyntaxException, NoSuchMethodException, InvocationTargetException, + IllegalAccessException, FileNotFoundException { + InputStream inputStream = new FileInputStream("src/test/resources/split_init.json"); + SplitClientConfig splitClientConfig = SplitClientConfig.builder() + .splitFile(inputStream, null) + .setBlockUntilReadyTimeout(10000) + .build(); + SplitFactoryImpl splitFactory = new SplitFactoryImpl("localhost", splitClientConfig); + + Method method = SplitFactoryImpl.class.getDeclaredMethod("createSplitChangeFetcher", SplitClientConfig.class); + method.setAccessible(true); + Object splitChangeFetcher = method.invoke(splitFactory, splitClientConfig); + Assert.assertTrue(splitChangeFetcher instanceof LegacyLocalhostSplitChangeFetcher); + } + + @Test + public void testLocalhosJsonInputStreamNullAndFileTypeNull() throws URISyntaxException, NoSuchMethodException, InvocationTargetException, + IllegalAccessException { + SplitClientConfig splitClientConfig = SplitClientConfig.builder() + .splitFile(null, null) + .setBlockUntilReadyTimeout(10000) + .build(); + SplitFactoryImpl splitFactory = new SplitFactoryImpl("localhost", splitClientConfig); - //inputStream is not null and filetype is not null - localhostPair = splitFactory.getInputStreamProviderAndFileType(null, inputStream, FileTypeEnum.JSON); - Assert.assertNotNull(localhostPair); + Method method = SplitFactoryImpl.class.getDeclaredMethod("createSplitChangeFetcher", SplitClientConfig.class); + method.setAccessible(true); + Object splitChangeFetcher = method.invoke(splitFactory, splitClientConfig); + Assert.assertTrue(splitChangeFetcher instanceof LegacyLocalhostSplitChangeFetcher); } } \ No newline at end of file diff --git a/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java index dabd96781..81c85a449 100644 --- a/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java @@ -2,6 +2,7 @@ import io.split.client.dtos.Split; import io.split.client.dtos.SplitChange; +import io.split.client.exceptions.InputStreamProviderException; import io.split.client.utils.FileInputStreamProvider; import io.split.client.utils.InputStreamProvider; import io.split.client.utils.LocalhostUtils; @@ -26,7 +27,7 @@ public class YamlLocalhostSplitChangeFetcherTest { public TemporaryFolder folder = new TemporaryFolder(); @Test - public void testParseSplitChange() throws IOException { + public void testParseSplitChange() throws IOException, InputStreamProviderException { File file = folder.newFile(SplitClientConfig.LOCALHOST_DEFAULT_FILE); List> allSplits = new ArrayList(); @@ -75,8 +76,8 @@ public void testParseSplitChange() throws IOException { } } - @Test(expected = IllegalStateException.class) - public void processTestForException() { + @Test(expected = InputStreamProviderException.class) + public void processTestForException() throws InputStreamProviderException { InputStreamProvider inputStreamProvider = new FileInputStreamProvider("src/test/resources/notExist.yaml"); YamlLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new YamlLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); diff --git a/client/src/test/java/io/split/engine/common/LocalhostSynchronizerTest.java b/client/src/test/java/io/split/engine/common/LocalhostSynchronizerTest.java index ed77888f0..70f3bc0ea 100644 --- a/client/src/test/java/io/split/engine/common/LocalhostSynchronizerTest.java +++ b/client/src/test/java/io/split/engine/common/LocalhostSynchronizerTest.java @@ -2,6 +2,7 @@ import io.split.client.LocalhostSegmentChangeFetcher; import io.split.client.JsonLocalhostSplitChangeFetcher; +import io.split.client.exceptions.InputStreamProviderException; import io.split.client.utils.FileInputStreamProvider; import io.split.client.utils.InputStreamProvider; import io.split.engine.experiments.SplitChangeFetcher; @@ -22,14 +23,12 @@ import org.junit.Test; import org.mockito.Mockito; -import java.io.FileNotFoundException; - public class LocalhostSynchronizerTest { private static final TelemetryStorage TELEMETRY_STORAGE_NOOP = Mockito.mock(NoopTelemetryStorage.class); @Test - public void testSyncAll() throws FileNotFoundException { + public void testSyncAll(){ SplitCache splitCacheProducer = new InMemoryCacheImp(); InputStreamProvider inputStreamProvider = new FileInputStreamProvider("src/test/resources/split_init.json"); @@ -52,7 +51,7 @@ public void testSyncAll() throws FileNotFoundException { } @Test - public void testPeriodicFetching() throws InterruptedException { + public void testPeriodicFetching() throws InterruptedException, InputStreamProviderException { SplitCache splitCacheProducer = new InMemoryCacheImp(); SplitChangeFetcher splitChangeFetcher = Mockito.mock(JsonLocalhostSplitChangeFetcher.class); @@ -79,7 +78,7 @@ public void testPeriodicFetching() throws InterruptedException { } @Test - public void testRefreshSplits() { + public void testRefreshSplits() throws InputStreamProviderException { SplitCacheProducer splitCacheProducer = new InMemoryCacheImp(); SplitChangeFetcher splitChangeFetcher = Mockito.mock(SplitChangeFetcher.class); SplitParser splitParser = new SplitParser(); diff --git a/client/src/test/java/io/split/engine/experiments/SplitFetcherTest.java b/client/src/test/java/io/split/engine/experiments/SplitFetcherTest.java index a6be86240..c186429ad 100644 --- a/client/src/test/java/io/split/engine/experiments/SplitFetcherTest.java +++ b/client/src/test/java/io/split/engine/experiments/SplitFetcherTest.java @@ -1,6 +1,7 @@ package io.split.engine.experiments; import com.google.common.collect.Lists; +import io.split.client.exceptions.InputStreamProviderException; import io.split.storages.memory.InMemoryCacheImp; import io.split.storages.SegmentCache; import io.split.storages.memory.SegmentCacheInMemoryImpl; @@ -87,7 +88,7 @@ private void works(long startingChangeNumber) throws InterruptedException { } @Test - public void when_parser_fails_we_remove_the_experiment() throws InterruptedException { + public void when_parser_fails_we_remove_the_experiment() throws InterruptedException, InputStreamProviderException { Split validSplit = new Split(); validSplit.status = Status.ACTIVE; validSplit.seed = (int) -1; @@ -213,7 +214,7 @@ public void works_with_user_defined_segments() throws Exception { } @Test - public void testBypassCdnClearedAfterFirstHit() { + public void testBypassCdnClearedAfterFirstHit() throws InputStreamProviderException { SplitChangeFetcher mockFetcher = Mockito.mock(SplitChangeFetcher.class); SplitParser mockParser = new SplitParser(); SplitCache mockCache = new InMemoryCacheImp(); diff --git a/client/src/test/java/io/split/engine/experiments/SplitSynchronizationTaskTest.java b/client/src/test/java/io/split/engine/experiments/SplitSynchronizationTaskTest.java index d53ac89e7..a15e7c7d0 100644 --- a/client/src/test/java/io/split/engine/experiments/SplitSynchronizationTaskTest.java +++ b/client/src/test/java/io/split/engine/experiments/SplitSynchronizationTaskTest.java @@ -1,6 +1,7 @@ package io.split.engine.experiments; import io.split.client.JsonLocalhostSplitChangeFetcher; +import io.split.client.exceptions.InputStreamProviderException; import io.split.engine.common.FetchOptions; import io.split.storages.SplitCacheProducer; import io.split.storages.memory.InMemoryCacheImp; @@ -14,7 +15,7 @@ public class SplitSynchronizationTaskTest { private static final TelemetryStorage TELEMETRY_STORAGE_NOOP = Mockito.mock(NoopTelemetryStorage.class); @Test - public void testLocalhost() throws InterruptedException { + public void testLocalhost() throws InterruptedException, InputStreamProviderException { SplitCacheProducer splitCacheProducer = new InMemoryCacheImp(); SplitChangeFetcher splitChangeFetcher = Mockito.mock(JsonLocalhostSplitChangeFetcher.class); From 06ed6e4e26e523bde3526b3b22bac1aa17d88ce0 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 1 Sep 2023 12:03:35 -0300 Subject: [PATCH 07/14] Add legacy message --- .../src/main/java/io/split/client/SplitFactoryImpl.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 80f4df244..e11346d72 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -115,6 +115,7 @@ public class SplitFactoryImpl implements SplitFactory { private static final Logger _log = LoggerFactory.getLogger(SplitFactory.class); + private static final String LEGACY_LOG_MESSAGE = "The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."; private final static long SSE_CONNECT_TIMEOUT = 30000; private final static long SSE_SOCKET_TIMEOUT = 70000; @@ -645,17 +646,17 @@ private SplitChangeFetcher createSplitChangeFetcher(SplitClientConfig splitClien FileTypeEnum fileType = splitClientConfig.fileType(); if (splitFile != null && inputStream != null) { _log.warn("splitFile or inputStreamProvider should have a value, not both"); - _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."); + _log.warn(LEGACY_LOG_MESSAGE); return new LegacyLocalhostSplitChangeFetcher(splitFile); } if (inputStream != null && fileType == null) { _log.warn("If inputStreamProvider is not null, then fileType must also have a non-null value"); - _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."); + _log.warn(LEGACY_LOG_MESSAGE); return new LegacyLocalhostSplitChangeFetcher(splitFile); } if (inputStream == null && splitFile == null){ _log.warn("splitFile or inputStreamProvider should have a value"); - _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."); + _log.warn(LEGACY_LOG_MESSAGE); return new LegacyLocalhostSplitChangeFetcher(splitFile); } if (splitFile != null) { @@ -684,7 +685,7 @@ private SplitChangeFetcher createSplitChangeFetcher(SplitClientConfig splitClien return new LegacyLocalhostSplitChangeFetcher(splitFile); } } - _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."); + _log.warn(LEGACY_LOG_MESSAGE); return new LegacyLocalhostSplitChangeFetcher(splitFile); } } \ No newline at end of file From ed595a1642a42801284b5f2bbfa03d6ab8ba8eaf Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 1 Sep 2023 12:19:54 -0300 Subject: [PATCH 08/14] Apply checkstyle --- client/src/main/java/io/split/client/SplitFactoryImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index e11346d72..c2533d8d9 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -115,7 +115,8 @@ public class SplitFactoryImpl implements SplitFactory { private static final Logger _log = LoggerFactory.getLogger(SplitFactory.class); - private static final String LEGACY_LOG_MESSAGE = "The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."; + private static final String LEGACY_LOG_MESSAGE = "The sdk initialize in localhost mode using Legacy file. The splitFile or " + + "inputStream doesn't add it to the config."; private final static long SSE_CONNECT_TIMEOUT = 30000; private final static long SSE_SOCKET_TIMEOUT = 70000; From 07ab95f008ef2b3adeb8a0d8b6e2d3d5c32759eb Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 1 Sep 2023 15:55:58 -0300 Subject: [PATCH 09/14] Update SplitFactoryImpl for localhost --- .../JsonLocalhostSplitChangeFetcher.java | 5 +- .../io/split/client/SplitFactoryImpl.java | 69 ++++++++++--------- .../YamlLocalhostSplitChangeFetcher.java | 4 +- .../experiments/SplitChangeFetcher.java | 3 +- .../engine/experiments/SplitFetcherImp.java | 3 +- .../JsonLocalhostSplitChangeFetcherTest.java | 17 +++-- .../YamlLocalhostSplitChangeFetcherTest.java | 7 +- .../common/LocalhostSynchronizerTest.java | 5 +- .../engine/experiments/SplitFetcherTest.java | 5 +- .../SplitSynchronizationTaskTest.java | 3 +- 10 files changed, 56 insertions(+), 65 deletions(-) diff --git a/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java b/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java index cf91712d3..e2cb5d5c9 100644 --- a/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/JsonLocalhostSplitChangeFetcher.java @@ -2,7 +2,6 @@ import com.google.gson.stream.JsonReader; import io.split.client.dtos.SplitChange; -import io.split.client.exceptions.InputStreamProviderException; import io.split.client.utils.InputStreamProvider; import io.split.client.utils.Json; import io.split.client.utils.LocalhostSanitizer; @@ -30,13 +29,11 @@ public JsonLocalhostSplitChangeFetcher(InputStreamProvider inputStreamProvider) } @Override - public SplitChange fetch(long since, FetchOptions options) throws InputStreamProviderException { + public SplitChange fetch(long since, FetchOptions options) { try { JsonReader jsonReader = new JsonReader(new BufferedReader(new InputStreamReader(_inputStreamProvider.get(), StandardCharsets.UTF_8))); SplitChange splitChange = Json.fromJson(jsonReader, SplitChange.class); return processSplitChange(splitChange, since); - } catch (InputStreamProviderException i) { - throw i; } catch (Exception e) { throw new IllegalStateException("Problem fetching splitChanges: " + e.getMessage(), e); } diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index c2533d8d9..f93b970cf 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -1,5 +1,6 @@ package io.split.client; +import com.google.common.io.Files; import io.split.client.dtos.Metadata; import io.split.client.events.EventsSender; import io.split.client.events.EventsStorage; @@ -32,6 +33,7 @@ import io.split.client.interceptors.SdkMetadataInterceptorFilter; import io.split.client.utils.FileInputStreamProvider; import io.split.client.utils.FileTypeEnum; +import io.split.client.utils.InputStreamProvider; import io.split.client.utils.InputStreamProviderImp; import io.split.client.utils.SDKMetadata; import io.split.engine.SDKReadinessGates; @@ -101,6 +103,7 @@ import org.slf4j.LoggerFactory; import pluggable.CustomStorageWrapper; +import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; @@ -645,48 +648,48 @@ private SplitChangeFetcher createSplitChangeFetcher(SplitClientConfig splitClien String splitFile = splitClientConfig.splitFile(); InputStream inputStream = splitClientConfig.inputStream(); FileTypeEnum fileType = splitClientConfig.fileType(); - if (splitFile != null && inputStream != null) { - _log.warn("splitFile or inputStreamProvider should have a value, not both"); - _log.warn(LEGACY_LOG_MESSAGE); - return new LegacyLocalhostSplitChangeFetcher(splitFile); - } - if (inputStream != null && fileType == null) { - _log.warn("If inputStreamProvider is not null, then fileType must also have a non-null value"); - _log.warn(LEGACY_LOG_MESSAGE); - return new LegacyLocalhostSplitChangeFetcher(splitFile); - } - if (inputStream == null && splitFile == null){ - _log.warn("splitFile or inputStreamProvider should have a value"); - _log.warn(LEGACY_LOG_MESSAGE); - return new LegacyLocalhostSplitChangeFetcher(splitFile); - } - if (splitFile != null) { - try { - if (splitFile.toLowerCase().endsWith(".json")) { - return new JsonLocalhostSplitChangeFetcher(new FileInputStreamProvider(splitFile)); - } else if (splitFile.endsWith(".yaml") || splitFile.endsWith(".yml")) { - return new YamlLocalhostSplitChangeFetcher(new FileInputStreamProvider(splitFile)); - } - } catch (Exception e) { - _log.warn(String.format("There was no file named %s found. " + - "We created a split client that returns default treatments for all feature flags for all of your users. " + - "If you wish to return a specific treatment for a feature flag, enter the name of that feature flag name and " + - "treatment name separated by whitespace in %s; one pair per line. Empty lines or lines starting with '#' are " + - "considered comments", - splitFile, splitFile), e); + InputStreamProvider inputStreamProvider; + if (splitFile != null || !isInputStreamConfigValid(inputStream, fileType)) { + if (splitFile == null) { + _log.warn("The InputStream config is invalid"); } + fileType = getFileTypeFromFileName(splitFile); + inputStreamProvider = new FileInputStreamProvider(splitFile); } else { - switch (fileType) { + inputStreamProvider = new InputStreamProviderImp(inputStream); + } + try { + switch (fileType){ case JSON: - return new JsonLocalhostSplitChangeFetcher(new InputStreamProviderImp(inputStream)); + return new JsonLocalhostSplitChangeFetcher(inputStreamProvider); case YAML: - return new YamlLocalhostSplitChangeFetcher(new InputStreamProviderImp(inputStream)); + return new YamlLocalhostSplitChangeFetcher(inputStreamProvider); default: - _log.warn("The sdk initialize in localhost mode using Legacy file. The splitFile or inputStream doesn't add it to the config."); + _log.warn(LEGACY_LOG_MESSAGE); return new LegacyLocalhostSplitChangeFetcher(splitFile); } + } catch (Exception e) { + _log.warn(String.format("There was no file named %s found. " + + "We created a split client that returns default treatments for all feature flags for all of your users. " + + "If you wish to return a specific treatment for a feature flag, enter the name of that feature flag name and " + + "treatment name separated by whitespace in %s; one pair per line. Empty lines or lines starting with '#' are " + + "considered comments", + splitFile, splitFile), e); } _log.warn(LEGACY_LOG_MESSAGE); return new LegacyLocalhostSplitChangeFetcher(splitFile); } + + private Boolean isInputStreamConfigValid(InputStream inputStream, FileTypeEnum fileType) { + return inputStream != null && fileType != null; + } + + private FileTypeEnum getFileTypeFromFileName(String fileName) { + try { + return FileTypeEnum.valueOf(Files.getFileExtension(fileName).toUpperCase()); + } catch (Exception e) { + return FileTypeEnum.LEGACY; + } + + } } \ No newline at end of file diff --git a/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java b/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java index 5d5a87c2f..745d1c5f6 100644 --- a/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java @@ -33,7 +33,7 @@ public YamlLocalhostSplitChangeFetcher(InputStreamProvider inputStreamProvider) } @Override - public SplitChange fetch(long since, FetchOptions options) throws InputStreamProviderException { + public SplitChange fetch(long since, FetchOptions options) { try { Yaml yaml = new Yaml(); List>> yamlSplits = yaml.load(_inputStreamProvider.get()); @@ -75,8 +75,6 @@ public SplitChange fetch(long since, FetchOptions options) throws InputStreamPro splitChange.till = since; splitChange.since = since; return splitChange; - } catch (InputStreamProviderException i) { - throw i; } catch (Exception e) { throw new IllegalStateException("Problem fetching splitChanges using a yaml file: " + e.getMessage(), e); } diff --git a/client/src/main/java/io/split/engine/experiments/SplitChangeFetcher.java b/client/src/main/java/io/split/engine/experiments/SplitChangeFetcher.java index c27fca1df..7c5fbe76e 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitChangeFetcher.java +++ b/client/src/main/java/io/split/engine/experiments/SplitChangeFetcher.java @@ -1,7 +1,6 @@ package io.split.engine.experiments; import io.split.client.dtos.SplitChange; -import io.split.client.exceptions.InputStreamProviderException; import io.split.engine.common.FetchOptions; /** @@ -33,5 +32,5 @@ public interface SplitChangeFetcher { * @return SegmentChange * @throws java.lang.RuntimeException if there was a problem computing split changes */ - SplitChange fetch(long since, FetchOptions options) throws InputStreamProviderException; + SplitChange fetch(long since, FetchOptions options); } diff --git a/client/src/main/java/io/split/engine/experiments/SplitFetcherImp.java b/client/src/main/java/io/split/engine/experiments/SplitFetcherImp.java index a94c07735..1043ccfcf 100644 --- a/client/src/main/java/io/split/engine/experiments/SplitFetcherImp.java +++ b/client/src/main/java/io/split/engine/experiments/SplitFetcherImp.java @@ -1,7 +1,6 @@ package io.split.engine.experiments; import io.split.client.dtos.SplitChange; -import io.split.client.exceptions.InputStreamProviderException; import io.split.client.utils.FeatureFlagsToUpdate; import io.split.storages.SplitCacheProducer; import io.split.telemetry.domain.enums.LastSynchronizationRecordsEnum; @@ -90,7 +89,7 @@ public void run() { this.forceRefresh(new FetchOptions.Builder().cacheControlHeaders(false).build()); } - private Set runWithoutExceptionHandling(FetchOptions options) throws InterruptedException, InputStreamProviderException { + private Set runWithoutExceptionHandling(FetchOptions options) throws InterruptedException { SplitChange change = _splitChangeFetcher.fetch(_splitCacheProducer.getChangeNumber(), options); Set segments = new HashSet<>(); diff --git a/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java index 9a9e4519e..e9a3c5cdd 100644 --- a/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java @@ -4,7 +4,6 @@ import io.split.client.dtos.Split; import io.split.client.dtos.SplitChange; import io.split.client.dtos.Status; -import io.split.client.exceptions.InputStreamProviderException; import io.split.client.utils.FileInputStreamProvider; import io.split.client.utils.InputStreamProvider; import io.split.client.utils.InputStreamProviderImp; @@ -34,7 +33,7 @@ public class JsonLocalhostSplitChangeFetcherTest { private String TEST_4 = "{\"splits\":[{\"trafficTypeName\":\"user\",\"name\":\"SPLIT_1\",\"trafficAllocation\":100,\"trafficAllocationSeed\":-1780071202,\"seed\":-1442762199,\"status\":\"ACTIVE\",\"killed\":false,\"defaultTreatment\":\"off\",\"changeNumber\":1675443537882,\"algo\":2,\"configurations\":{},\"conditions\":[{\"conditionType\":\"ROLLOUT\",\"matcherGroup\":{\"combiner\":\"AND\",\"matchers\":[{\"keySelector\":{\"trafficType\":\"user\",\"attribute\":null},\"matcherType\":\"ALL_KEYS\",\"negate\":false,\"userDefinedSegmentMatcherData\":null,\"whitelistMatcherData\":null,\"unaryNumericMatcherData\":null,\"betweenMatcherData\":null,\"booleanMatcherData\":null,\"dependencyMatcherData\":null,\"stringMatcherData\":null}]},\"partitions\":[{\"treatment\":\"on\",\"size\":0},{\"treatment\":\"off\",\"size\":100}],\"label\":\"default rule\"}]}],\"since\":-1,\"till\":445345}"; private String TEST_5 = "{\"splits\":[{\"trafficTypeName\":\"user\",\"name\":\"SPLIT_1\",\"trafficAllocation\":100,\"trafficAllocationSeed\":-1780071202,\"seed\":-1442762199,\"status\":\"ACTIVE\",\"killed\":false,\"defaultTreatment\":\"off\",\"changeNumber\":1675443537882,\"algo\":2,\"configurations\":{},\"conditions\":[{\"conditionType\":\"ROLLOUT\",\"matcherGroup\":{\"combiner\":\"AND\",\"matchers\":[{\"keySelector\":{\"trafficType\":\"user\",\"attribute\":null},\"matcherType\":\"ALL_KEYS\",\"negate\":false,\"userDefinedSegmentMatcherData\":null,\"whitelistMatcherData\":null,\"unaryNumericMatcherData\":null,\"betweenMatcherData\":null,\"booleanMatcherData\":null,\"dependencyMatcherData\":null,\"stringMatcherData\":null}]},\"partitions\":[{\"treatment\":\"on\",\"size\":0},{\"treatment\":\"off\",\"size\":100}],\"label\":\"default rule\"}]},{\"trafficTypeName\":\"user\",\"name\":\"SPLIT_2\",\"trafficAllocation\":100,\"trafficAllocationSeed\":-1780071202,\"seed\":-1442762199,\"status\":\"ACTIVE\",\"killed\":false,\"defaultTreatment\":\"off\",\"changeNumber\":1675443537882,\"algo\":2,\"configurations\":{},\"conditions\":[{\"conditionType\":\"ROLLOUT\",\"matcherGroup\":{\"combiner\":\"AND\",\"matchers\":[{\"keySelector\":{\"trafficType\":\"user\",\"attribute\":null},\"matcherType\":\"ALL_KEYS\",\"negate\":false,\"userDefinedSegmentMatcherData\":null,\"whitelistMatcherData\":null,\"unaryNumericMatcherData\":null,\"betweenMatcherData\":null,\"booleanMatcherData\":null,\"dependencyMatcherData\":null,\"stringMatcherData\":null}]},\"partitions\":[{\"treatment\":\"on\",\"size\":0},{\"treatment\":\"off\",\"size\":100}],\"label\":\"default rule\"}]}],\"since\":-1,\"till\":-1}"; @Test - public void testParseSplitChange() throws FileNotFoundException, InputStreamProviderException { + public void testParseSplitChange() throws FileNotFoundException { InputStream inputStream = new FileInputStream("src/test/resources/split_init.json"); InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); @@ -49,7 +48,7 @@ public void testParseSplitChange() throws FileNotFoundException, InputStreamProv } @Test - public void testSinceAndTillSanitization() throws FileNotFoundException, InputStreamProviderException { + public void testSinceAndTillSanitization() throws FileNotFoundException { InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangeTillSanitization.json"); InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); @@ -62,7 +61,7 @@ public void testSinceAndTillSanitization() throws FileNotFoundException, InputSt } @Test - public void testSplitChangeWithoutSplits() throws FileNotFoundException, InputStreamProviderException { + public void testSplitChangeWithoutSplits() throws FileNotFoundException { InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangeWithoutSplits.json"); InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); @@ -74,7 +73,7 @@ public void testSplitChangeWithoutSplits() throws FileNotFoundException, InputSt } @Test - public void testSplitChangeSplitsToSanitize() throws FileNotFoundException, InputStreamProviderException { + public void testSplitChangeSplitsToSanitize() throws FileNotFoundException { InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangeSplitsToSanitize.json"); InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); @@ -91,7 +90,7 @@ public void testSplitChangeSplitsToSanitize() throws FileNotFoundException, Inpu } @Test - public void testSplitChangeSplitsToSanitizeMatchersNull() throws FileNotFoundException, InputStreamProviderException { + public void testSplitChangeSplitsToSanitizeMatchersNull() throws FileNotFoundException { InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangerMatchersNull.json"); InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); @@ -108,7 +107,7 @@ public void testSplitChangeSplitsToSanitizeMatchersNull() throws FileNotFoundExc } @Test - public void testSplitChangeSplitsDifferentScenarios() throws IOException, InputStreamProviderException { + public void testSplitChangeSplitsDifferentScenarios() throws IOException { File file = folder.newFile("test_0.json"); @@ -171,8 +170,8 @@ public void testSplitChangeSplitsDifferentScenarios() throws IOException, InputS Assert.assertEquals(2323, splitChange.since); } - @Test(expected = InputStreamProviderException.class) - public void processTestForException() throws InputStreamProviderException { + @Test(expected = IllegalStateException.class) + public void processTestForException() { InputStreamProvider inputStreamProvider = new FileInputStreamProvider("src/test/resources/notExist.json"); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); diff --git a/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java index 81c85a449..dabd96781 100644 --- a/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/YamlLocalhostSplitChangeFetcherTest.java @@ -2,7 +2,6 @@ import io.split.client.dtos.Split; import io.split.client.dtos.SplitChange; -import io.split.client.exceptions.InputStreamProviderException; import io.split.client.utils.FileInputStreamProvider; import io.split.client.utils.InputStreamProvider; import io.split.client.utils.LocalhostUtils; @@ -27,7 +26,7 @@ public class YamlLocalhostSplitChangeFetcherTest { public TemporaryFolder folder = new TemporaryFolder(); @Test - public void testParseSplitChange() throws IOException, InputStreamProviderException { + public void testParseSplitChange() throws IOException { File file = folder.newFile(SplitClientConfig.LOCALHOST_DEFAULT_FILE); List> allSplits = new ArrayList(); @@ -76,8 +75,8 @@ public void testParseSplitChange() throws IOException, InputStreamProviderExcept } } - @Test(expected = InputStreamProviderException.class) - public void processTestForException() throws InputStreamProviderException { + @Test(expected = IllegalStateException.class) + public void processTestForException() { InputStreamProvider inputStreamProvider = new FileInputStreamProvider("src/test/resources/notExist.yaml"); YamlLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new YamlLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); diff --git a/client/src/test/java/io/split/engine/common/LocalhostSynchronizerTest.java b/client/src/test/java/io/split/engine/common/LocalhostSynchronizerTest.java index 70f3bc0ea..4981cd6cc 100644 --- a/client/src/test/java/io/split/engine/common/LocalhostSynchronizerTest.java +++ b/client/src/test/java/io/split/engine/common/LocalhostSynchronizerTest.java @@ -2,7 +2,6 @@ import io.split.client.LocalhostSegmentChangeFetcher; import io.split.client.JsonLocalhostSplitChangeFetcher; -import io.split.client.exceptions.InputStreamProviderException; import io.split.client.utils.FileInputStreamProvider; import io.split.client.utils.InputStreamProvider; import io.split.engine.experiments.SplitChangeFetcher; @@ -51,7 +50,7 @@ public void testSyncAll(){ } @Test - public void testPeriodicFetching() throws InterruptedException, InputStreamProviderException { + public void testPeriodicFetching() throws InterruptedException { SplitCache splitCacheProducer = new InMemoryCacheImp(); SplitChangeFetcher splitChangeFetcher = Mockito.mock(JsonLocalhostSplitChangeFetcher.class); @@ -78,7 +77,7 @@ public void testPeriodicFetching() throws InterruptedException, InputStreamProvi } @Test - public void testRefreshSplits() throws InputStreamProviderException { + public void testRefreshSplits() { SplitCacheProducer splitCacheProducer = new InMemoryCacheImp(); SplitChangeFetcher splitChangeFetcher = Mockito.mock(SplitChangeFetcher.class); SplitParser splitParser = new SplitParser(); diff --git a/client/src/test/java/io/split/engine/experiments/SplitFetcherTest.java b/client/src/test/java/io/split/engine/experiments/SplitFetcherTest.java index c186429ad..a6be86240 100644 --- a/client/src/test/java/io/split/engine/experiments/SplitFetcherTest.java +++ b/client/src/test/java/io/split/engine/experiments/SplitFetcherTest.java @@ -1,7 +1,6 @@ package io.split.engine.experiments; import com.google.common.collect.Lists; -import io.split.client.exceptions.InputStreamProviderException; import io.split.storages.memory.InMemoryCacheImp; import io.split.storages.SegmentCache; import io.split.storages.memory.SegmentCacheInMemoryImpl; @@ -88,7 +87,7 @@ private void works(long startingChangeNumber) throws InterruptedException { } @Test - public void when_parser_fails_we_remove_the_experiment() throws InterruptedException, InputStreamProviderException { + public void when_parser_fails_we_remove_the_experiment() throws InterruptedException { Split validSplit = new Split(); validSplit.status = Status.ACTIVE; validSplit.seed = (int) -1; @@ -214,7 +213,7 @@ public void works_with_user_defined_segments() throws Exception { } @Test - public void testBypassCdnClearedAfterFirstHit() throws InputStreamProviderException { + public void testBypassCdnClearedAfterFirstHit() { SplitChangeFetcher mockFetcher = Mockito.mock(SplitChangeFetcher.class); SplitParser mockParser = new SplitParser(); SplitCache mockCache = new InMemoryCacheImp(); diff --git a/client/src/test/java/io/split/engine/experiments/SplitSynchronizationTaskTest.java b/client/src/test/java/io/split/engine/experiments/SplitSynchronizationTaskTest.java index a15e7c7d0..d53ac89e7 100644 --- a/client/src/test/java/io/split/engine/experiments/SplitSynchronizationTaskTest.java +++ b/client/src/test/java/io/split/engine/experiments/SplitSynchronizationTaskTest.java @@ -1,7 +1,6 @@ package io.split.engine.experiments; import io.split.client.JsonLocalhostSplitChangeFetcher; -import io.split.client.exceptions.InputStreamProviderException; import io.split.engine.common.FetchOptions; import io.split.storages.SplitCacheProducer; import io.split.storages.memory.InMemoryCacheImp; @@ -15,7 +14,7 @@ public class SplitSynchronizationTaskTest { private static final TelemetryStorage TELEMETRY_STORAGE_NOOP = Mockito.mock(NoopTelemetryStorage.class); @Test - public void testLocalhost() throws InterruptedException, InputStreamProviderException { + public void testLocalhost() throws InterruptedException { SplitCacheProducer splitCacheProducer = new InMemoryCacheImp(); SplitChangeFetcher splitChangeFetcher = Mockito.mock(JsonLocalhostSplitChangeFetcher.class); From d9104b689e97b15a617cbbd947fd4c4d8044bdfa Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 1 Sep 2023 16:11:26 -0300 Subject: [PATCH 10/14] Remove code smell --- client/src/main/java/io/split/client/SplitFactoryImpl.java | 1 - .../java/io/split/client/YamlLocalhostSplitChangeFetcher.java | 1 - 2 files changed, 2 deletions(-) diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index f93b970cf..8dff2c79d 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -103,7 +103,6 @@ import org.slf4j.LoggerFactory; import pluggable.CustomStorageWrapper; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; diff --git a/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java b/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java index 745d1c5f6..e90ca1389 100644 --- a/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java +++ b/client/src/main/java/io/split/client/YamlLocalhostSplitChangeFetcher.java @@ -5,7 +5,6 @@ import io.split.client.dtos.Split; import io.split.client.dtos.SplitChange; import io.split.client.dtos.Status; -import io.split.client.exceptions.InputStreamProviderException; import io.split.client.utils.InputStreamProvider; import io.split.client.utils.LocalhostConstants; import io.split.engine.common.FetchOptions; From acbebf4e776c698f7fc4023e62e882f342853c94 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Fri, 1 Sep 2023 18:50:36 -0300 Subject: [PATCH 11/14] Add StaticContentInputStreamProviver --- .../io/split/client/SplitFactoryImpl.java | 4 +-- .../client/utils/InputStreamProviderImp.java | 18 ------------- .../StaticContentInputStreamProvider.java | 26 +++++++++++++++++++ .../JsonLocalhostSplitChangeFetcherTest.java | 12 ++++----- .../SegmentSynchronizationTaskImpTest.java | 4 +-- 5 files changed, 36 insertions(+), 28 deletions(-) delete mode 100644 client/src/main/java/io/split/client/utils/InputStreamProviderImp.java create mode 100644 client/src/main/java/io/split/client/utils/StaticContentInputStreamProvider.java diff --git a/client/src/main/java/io/split/client/SplitFactoryImpl.java b/client/src/main/java/io/split/client/SplitFactoryImpl.java index 8dff2c79d..88413bdbd 100644 --- a/client/src/main/java/io/split/client/SplitFactoryImpl.java +++ b/client/src/main/java/io/split/client/SplitFactoryImpl.java @@ -34,8 +34,8 @@ import io.split.client.utils.FileInputStreamProvider; import io.split.client.utils.FileTypeEnum; import io.split.client.utils.InputStreamProvider; -import io.split.client.utils.InputStreamProviderImp; import io.split.client.utils.SDKMetadata; +import io.split.client.utils.StaticContentInputStreamProvider; import io.split.engine.SDKReadinessGates; import io.split.engine.common.ConsumerSyncManager; import io.split.engine.common.ConsumerSynchronizer; @@ -655,7 +655,7 @@ private SplitChangeFetcher createSplitChangeFetcher(SplitClientConfig splitClien fileType = getFileTypeFromFileName(splitFile); inputStreamProvider = new FileInputStreamProvider(splitFile); } else { - inputStreamProvider = new InputStreamProviderImp(inputStream); + inputStreamProvider = new StaticContentInputStreamProvider(inputStream); } try { switch (fileType){ diff --git a/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java b/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java deleted file mode 100644 index 4b945fcd3..000000000 --- a/client/src/main/java/io/split/client/utils/InputStreamProviderImp.java +++ /dev/null @@ -1,18 +0,0 @@ -package io.split.client.utils; - -import io.split.client.exceptions.InputStreamProviderException; - -import java.io.InputStream; - -public class InputStreamProviderImp implements InputStreamProvider { - private final InputStream _inputStream; - - public InputStreamProviderImp(InputStream inputStream){ - _inputStream = inputStream; - } - - @Override - public InputStream get() throws InputStreamProviderException { - return _inputStream; - } -} \ No newline at end of file diff --git a/client/src/main/java/io/split/client/utils/StaticContentInputStreamProvider.java b/client/src/main/java/io/split/client/utils/StaticContentInputStreamProvider.java new file mode 100644 index 000000000..d129b77c8 --- /dev/null +++ b/client/src/main/java/io/split/client/utils/StaticContentInputStreamProvider.java @@ -0,0 +1,26 @@ +package io.split.client.utils; + +import io.split.client.exceptions.InputStreamProviderException; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.stream.Collectors; + +public class StaticContentInputStreamProvider implements InputStreamProvider { + + private final String _streamContents; + + public StaticContentInputStreamProvider(InputStream inputStream){ + _streamContents = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8)) + .lines() + .collect(Collectors.joining("\n")); + } + + @Override + public InputStream get() throws InputStreamProviderException { + return new ByteArrayInputStream(_streamContents.getBytes()); + } +} diff --git a/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java b/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java index e9a3c5cdd..c355734aa 100644 --- a/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java +++ b/client/src/test/java/io/split/client/JsonLocalhostSplitChangeFetcherTest.java @@ -6,7 +6,7 @@ import io.split.client.dtos.Status; import io.split.client.utils.FileInputStreamProvider; import io.split.client.utils.InputStreamProvider; -import io.split.client.utils.InputStreamProviderImp; +import io.split.client.utils.StaticContentInputStreamProvider; import io.split.engine.common.FetchOptions; import org.junit.Assert; import org.junit.Rule; @@ -35,7 +35,7 @@ public class JsonLocalhostSplitChangeFetcherTest { @Test public void testParseSplitChange() throws FileNotFoundException { InputStream inputStream = new FileInputStream("src/test/resources/split_init.json"); - InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); + InputStreamProvider inputStreamProvider = new StaticContentInputStreamProvider(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); @@ -50,7 +50,7 @@ public void testParseSplitChange() throws FileNotFoundException { @Test public void testSinceAndTillSanitization() throws FileNotFoundException { InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangeTillSanitization.json"); - InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); + InputStreamProvider inputStreamProvider = new StaticContentInputStreamProvider(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); @@ -63,7 +63,7 @@ public void testSinceAndTillSanitization() throws FileNotFoundException { @Test public void testSplitChangeWithoutSplits() throws FileNotFoundException { InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangeWithoutSplits.json"); - InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); + InputStreamProvider inputStreamProvider = new StaticContentInputStreamProvider(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); @@ -75,7 +75,7 @@ public void testSplitChangeWithoutSplits() throws FileNotFoundException { @Test public void testSplitChangeSplitsToSanitize() throws FileNotFoundException { InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangeSplitsToSanitize.json"); - InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); + InputStreamProvider inputStreamProvider = new StaticContentInputStreamProvider(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); @@ -92,7 +92,7 @@ public void testSplitChangeSplitsToSanitize() throws FileNotFoundException { @Test public void testSplitChangeSplitsToSanitizeMatchersNull() throws FileNotFoundException { InputStream inputStream = new FileInputStream("src/test/resources/sanitizer/splitChangerMatchersNull.json"); - InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); + InputStreamProvider inputStreamProvider = new StaticContentInputStreamProvider(inputStream); JsonLocalhostSplitChangeFetcher localhostSplitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); FetchOptions fetchOptions = Mockito.mock(FetchOptions.class); diff --git a/client/src/test/java/io/split/engine/segments/SegmentSynchronizationTaskImpTest.java b/client/src/test/java/io/split/engine/segments/SegmentSynchronizationTaskImpTest.java index 50ce80f2f..32ba6fa0b 100644 --- a/client/src/test/java/io/split/engine/segments/SegmentSynchronizationTaskImpTest.java +++ b/client/src/test/java/io/split/engine/segments/SegmentSynchronizationTaskImpTest.java @@ -4,7 +4,7 @@ import io.split.client.LocalhostSegmentChangeFetcher; import io.split.client.JsonLocalhostSplitChangeFetcher; import io.split.client.utils.InputStreamProvider; -import io.split.client.utils.InputStreamProviderImp; +import io.split.client.utils.StaticContentInputStreamProvider; import io.split.engine.common.FetchOptions; import io.split.engine.experiments.SplitChangeFetcher; import io.split.engine.experiments.SplitFetcher; @@ -155,7 +155,7 @@ public void testLocalhostSegmentChangeFetcher() throws InterruptedException, Fil SplitCache splitCacheProducer = new InMemoryCacheImp(); InputStream inputStream = new FileInputStream("src/test/resources/split_init.json"); - InputStreamProvider inputStreamProvider = new InputStreamProviderImp(inputStream); + InputStreamProvider inputStreamProvider = new StaticContentInputStreamProvider(inputStream); SplitChangeFetcher splitChangeFetcher = new JsonLocalhostSplitChangeFetcher(inputStreamProvider); SplitParser splitParser = new SplitParser(); FetchOptions fetchOptions = new FetchOptions.Builder().build(); From 50c0e331c8cd88b2c739dbd3f0c00b7a0387bdce Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 7 Sep 2023 10:23:58 -0300 Subject: [PATCH 12/14] Update version to check in tapps --- client/pom.xml | 2 +- pluggable-storage/pom.xml | 2 +- pom.xml | 2 +- redis-wrapper/pom.xml | 2 +- testing/pom.xml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/pom.xml b/client/pom.xml index a775f5fb4..97960e23e 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.8.1 + 4.9.0-rc1 java-client jar diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml index f2a69fc6a..c77202cd4 100644 --- a/pluggable-storage/pom.xml +++ b/pluggable-storage/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.8.1 + 4.9.0-rc1 2.0.0 diff --git a/pom.xml b/pom.xml index 9b4160086..f5a8f8f3a 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.split.client java-client-parent - 4.8.1 + 4.9.0-rc1 diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml index 99b77073e..8ebd865fa 100644 --- a/redis-wrapper/pom.xml +++ b/redis-wrapper/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.8.1 + 4.9.0-rc1 redis-wrapper 3.0.1 diff --git a/testing/pom.xml b/testing/pom.xml index d35996d06..6bcfccc90 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.8.1 + 4.9.0-rc1 java-client-testing jar From 1bd2bde48e2ee86db06bdd85d02748c112555190 Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 7 Sep 2023 16:10:30 -0300 Subject: [PATCH 13/14] [SDKS-7515] Update changelog and client version --- CHANGES.txt | 5 +++++ client/pom.xml | 2 +- pluggable-storage/pom.xml | 2 +- pom.xml | 2 +- redis-wrapper/pom.xml | 2 +- testing/pom.xml | 2 +- 6 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 44b8d4593..93d1fa4d0 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,8 @@ +4.9.0 (Sep 7, 2023) +- Added InputStream config for localhost mode providing a solution when the file is inside a jar. +- Updated track impressions to send all impressions to the listener. +- Updated SyncManager shutdown to stop SSE only when is streaming mode on. + 4.8.1 (Aug 1, 2023) - Applied linting rules to the code. - Fixed an issue when the prefix is empty for Redis settings. diff --git a/client/pom.xml b/client/pom.xml index 97960e23e..5808ac722 100644 --- a/client/pom.xml +++ b/client/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.9.0-rc1 + 4.9.0 java-client jar diff --git a/pluggable-storage/pom.xml b/pluggable-storage/pom.xml index c77202cd4..290fe939d 100644 --- a/pluggable-storage/pom.xml +++ b/pluggable-storage/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.9.0-rc1 + 4.9.0 2.0.0 diff --git a/pom.xml b/pom.xml index f5a8f8f3a..4536b6a2a 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 io.split.client java-client-parent - 4.9.0-rc1 + 4.9.0 diff --git a/redis-wrapper/pom.xml b/redis-wrapper/pom.xml index 8ebd865fa..c733a21ab 100644 --- a/redis-wrapper/pom.xml +++ b/redis-wrapper/pom.xml @@ -6,7 +6,7 @@ java-client-parent io.split.client - 4.9.0-rc1 + 4.9.0 redis-wrapper 3.0.1 diff --git a/testing/pom.xml b/testing/pom.xml index 6bcfccc90..11160430e 100644 --- a/testing/pom.xml +++ b/testing/pom.xml @@ -5,7 +5,7 @@ io.split.client java-client-parent - 4.9.0-rc1 + 4.9.0 java-client-testing jar From 8fd40196ccd98d1543b985edd32098bb27a34b3e Mon Sep 17 00:00:00 2001 From: Nadia Mayor Date: Thu, 7 Sep 2023 17:16:04 -0300 Subject: [PATCH 14/14] Update changelog --- CHANGES.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 93d1fa4d0..1fcca8ad2 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,7 +1,7 @@ 4.9.0 (Sep 7, 2023) - Added InputStream config for localhost mode providing a solution when the file is inside a jar. -- Updated track impressions to send all impressions to the listener. -- Updated SyncManager shutdown to stop SSE only when is streaming mode on. +- Fixed track impressions to send all impressions to the listener. +- Fixed SyncManager shutdown to stop SSE only when is streaming mode on. 4.8.1 (Aug 1, 2023) - Applied linting rules to the code.