From 20cde708d7d7c5dc879085ec06defebe75637649 Mon Sep 17 00:00:00 2001 From: Roger Floriano <31597636+petruki@users.noreply.github.com> Date: Sat, 21 Jun 2025 12:21:51 -0700 Subject: [PATCH 1/2] Added switcher.snapshot.watcher configuration (#347) --- README.md | 15 +++- .../switcherapi/client/ContextBuilder.java | 9 +++ .../switcherapi/client/SwitcherConfig.java | 10 +++ .../client/SwitcherContextBase.java | 22 +++++- .../client/SwitcherPropertiesImpl.java | 46 ++++++----- .../switcherapi/client/model/ContextKey.java | 5 ++ .../client/utils/SnapshotTest.java | 77 +++++++++++++++++++ .../utils/SnapshotWatcherContextTest.java | 69 +++++++++++++++++ .../client/utils/SnapshotWatcherTest.java | 65 +--------------- .../utils/SnapshotWatcherWorkerTest.java | 19 +---- src/test/resources/switcherapi.properties | 1 + 11 files changed, 231 insertions(+), 107 deletions(-) create mode 100644 src/test/java/com/github/switcherapi/client/utils/SnapshotTest.java create mode 100644 src/test/java/com/github/switcherapi/client/utils/SnapshotWatcherContextTest.java diff --git a/README.md b/README.md index 9b33a3f..5cb5c87 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,7 @@ switcher.check -> true/false When true, it will check Switcher Keys switcher.relay.restrict -> true/false When true, it will check snapshot relay status switcher.snapshot.location -> Folder from where snapshots will be saved/read switcher.snapshot.auto -> true/false Automated lookup for snapshot when initializing the client +switcher.snapshot.watcher -> true/false Enable the watcher to monitor the snapshot file for changes during runtime switcher.snapshot.skipvalidation -> true/false Skip snapshotValidation() that can be used for UT executions switcher.snapshot.updateinterval -> Enable the Snapshot Auto Update given an interval of time - e.g. 1s (s: seconds, m: minutes) switcher.silent -> Enable contigency given the time for the client to retry - e.g. 5s (s: seconds - m: minutes - h: hours) @@ -252,9 +253,9 @@ MyAppFeatures.scheduleSnapshotAutoUpdate("5s", new SnapshotCallback() { }); ``` -## Real-time snapshot reload +## Real-time snapshot reload (Hot-swapping) Let the Switcher Client manage your application local snapshot.
-These features allow you to configure the SDK to automatically update the snapshot in the background. +These features allow you to configure the SDK to automatically update the snapshot during runtime. 1. This feature will update the in-memory Snapshot every time the file is modified. @@ -263,6 +264,15 @@ MyAppFeatures.watchSnapshot(); MyAppFeatures.stopWatchingSnapshot(); ``` +Alternatively, you can also set the Switcher Context configuration to start watching the snapshot file during the client initialization. + +```java +MyAppFeatures.configure(ContextBuilder.builder() + .snapshotWatcher(true)); + +MyAppFeatures.initializeClient(); +``` + 2. You can also perform snapshot update validation to verify if there are changes to be pulled. ```java @@ -319,7 +329,6 @@ Alternatively, you can also set the Switcher Context configuration to check duri ```java MyAppFeatures.configure(ContextBuilder.builder() - ... .checkSwitchers(true)); MyAppFeatures.initializeClient(); diff --git a/src/main/java/com/github/switcherapi/client/ContextBuilder.java b/src/main/java/com/github/switcherapi/client/ContextBuilder.java index 15b5139..7d3930c 100644 --- a/src/main/java/com/github/switcherapi/client/ContextBuilder.java +++ b/src/main/java/com/github/switcherapi/client/ContextBuilder.java @@ -159,6 +159,15 @@ public ContextBuilder snapshotSkipValidation(boolean snapshotSkipValidation) { return this; } + /** + * @param snapshotWatcher true/false When true, it will watch the snapshot file for changes and update the switchers accordingly + * @return ContextBuilder + */ + public ContextBuilder snapshotWatcher(boolean snapshotWatcher) { + switcherProperties.setValue(ContextKey.SNAPSHOT_WATCHER, snapshotWatcher); + return this; + } + /** * @param retryAfter Enable contingency given the time for the client to retry - e.g. 5s (s: seconds - m: minutes - h: hours) * @return ContextBuilder diff --git a/src/main/java/com/github/switcherapi/client/SwitcherConfig.java b/src/main/java/com/github/switcherapi/client/SwitcherConfig.java index e7db78d..b3dee9e 100644 --- a/src/main/java/com/github/switcherapi/client/SwitcherConfig.java +++ b/src/main/java/com/github/switcherapi/client/SwitcherConfig.java @@ -51,6 +51,7 @@ protected void updateSwitcherConfig(SwitcherProperties properties) { snapshotConfig.setLocation(properties.getValue(ContextKey.SNAPSHOT_LOCATION)); snapshotConfig.setAuto(properties.getBoolean(ContextKey.SNAPSHOT_AUTO_LOAD)); snapshotConfig.setSkipValidation(properties.getBoolean(ContextKey.SNAPSHOT_SKIP_VALIDATION)); + snapshotConfig.setWatcher(properties.getBoolean(ContextKey.SNAPSHOT_WATCHER)); snapshotConfig.setUpdateInterval(properties.getValue(ContextKey.SNAPSHOT_AUTO_UPDATE_INTERVAL)); setSnapshot(snapshotConfig); @@ -148,6 +149,7 @@ public static class SnapshotConfig { private String location; private boolean auto; private boolean skipValidation; + private boolean watcher; private String updateInterval; public String getLocation() { @@ -174,6 +176,14 @@ public void setSkipValidation(boolean skipValidation) { this.skipValidation = skipValidation; } + public boolean isWatcher() { + return watcher; + } + + public void setWatcher(boolean watcher) { + this.watcher = watcher; + } + public String getUpdateInterval() { return updateInterval; } diff --git a/src/main/java/com/github/switcherapi/client/SwitcherContextBase.java b/src/main/java/com/github/switcherapi/client/SwitcherContextBase.java index f7f7aba..b5013ab 100644 --- a/src/main/java/com/github/switcherapi/client/SwitcherContextBase.java +++ b/src/main/java/com/github/switcherapi/client/SwitcherContextBase.java @@ -115,6 +115,7 @@ protected void configureClient() { .poolConnectionSize(poolSize) .snapshotLocation(snapshot.getLocation()) .snapshotAutoLoad(snapshot.isAuto()) + .snapshotWatcher(snapshot.isWatcher()) .snapshotSkipValidation(snapshot.isSkipValidation()) .snapshotAutoUpdateInterval(snapshot.getUpdateInterval()) .truststorePath(truststore.getPath()) @@ -185,6 +186,7 @@ public static void initializeClient() { switcherExecutor = buildInstance(); loadSwitchers(); + scheduleSnapshotWatcher(); scheduleSnapshotAutoUpdate(contextStr(ContextKey.SNAPSHOT_AUTO_UPDATE_INTERVAL)); ContextBuilder.preConfigure(switcherProperties); SwitcherUtils.debug(logger, "Switcher Client initialized"); @@ -270,6 +272,18 @@ private static void loadSwitchers() throws SwitchersValidationException { } } + /** + * Schedule a task to watch the snapshot file for modifications.
+ * The task will be executed in a single thread executor service. + *

+ * (*) Requires client to use local settings + */ + private static void scheduleSnapshotWatcher() { + if (contextBol(ContextKey.SNAPSHOT_WATCHER)) { + watchSnapshot(); + } + } + /** * Schedule a task to update the snapshot automatically.
* The task will be executed in a single thread executor service. @@ -388,8 +402,8 @@ public static SwitcherRequest getSwitcher(String key) { } /** - * Validate if the snapshot version is the same as the one in the API.
- * If the version is different, it will update the snapshot in memory. + * Validate if the local snapshot version is the same as remote.
+ * If the version is different, it will update the local snapshot. * * @return true if snapshot was updated */ @@ -404,7 +418,7 @@ public static boolean validateSnapshot() { /** * Start watching snapshot files for modifications.
- * When the file is modified the in-memory snapshot will reload + * When the file is modified the local snapshot will reload * *

* (*) Requires client to use local settings @@ -415,7 +429,7 @@ public static void watchSnapshot() { /** * Start watching snapshot files for modifications.
- * When the file is modified the in-memory snapshot will reload + * When the file is modified the local snapshot will reload * *

* (*) Requires client to use local settings diff --git a/src/main/java/com/github/switcherapi/client/SwitcherPropertiesImpl.java b/src/main/java/com/github/switcherapi/client/SwitcherPropertiesImpl.java index ea0f88e..8c832c1 100644 --- a/src/main/java/com/github/switcherapi/client/SwitcherPropertiesImpl.java +++ b/src/main/java/com/github/switcherapi/client/SwitcherPropertiesImpl.java @@ -2,7 +2,6 @@ import com.github.switcherapi.client.exception.SwitcherContextException; import com.github.switcherapi.client.model.ContextKey; -import com.github.switcherapi.client.utils.SwitcherUtils; import org.apache.commons.lang3.StringUtils; import java.util.HashMap; @@ -10,18 +9,24 @@ import java.util.Properties; import static com.github.switcherapi.client.remote.Constants.*; +import static com.github.switcherapi.client.utils.SwitcherUtils.*; public class SwitcherPropertiesImpl implements SwitcherProperties { private final Map properties = new HashMap<>(); public SwitcherPropertiesImpl() { + initDefaults(); + } + + private void initDefaults() { setValue(ContextKey.ENVIRONMENT, DEFAULT_ENV); setValue(ContextKey.REGEX_TIMEOUT, DEFAULT_REGEX_TIMEOUT); setValue(ContextKey.TIMEOUT_MS, DEFAULT_TIMEOUT); setValue(ContextKey.POOL_CONNECTION_SIZE, DEFAULT_POOL_SIZE); setValue(ContextKey.SNAPSHOT_AUTO_LOAD, false); setValue(ContextKey.SNAPSHOT_SKIP_VALIDATION, false); + setValue(ContextKey.SNAPSHOT_WATCHER, false); setValue(ContextKey.LOCAL_MODE, false); setValue(ContextKey.CHECK_SWITCHERS, false); setValue(ContextKey.RESTRICT_RELAY, true); @@ -29,25 +34,26 @@ public SwitcherPropertiesImpl() { @Override public void loadFromProperties(Properties prop) { - setValue(ContextKey.CONTEXT_LOCATION, SwitcherUtils.resolveProperties(ContextKey.CONTEXT_LOCATION.getParam(), prop)); - setValue(ContextKey.URL, SwitcherUtils.resolveProperties(ContextKey.URL.getParam(), prop)); - setValue(ContextKey.APIKEY, SwitcherUtils.resolveProperties(ContextKey.APIKEY.getParam(), prop)); - setValue(ContextKey.DOMAIN, SwitcherUtils.resolveProperties(ContextKey.DOMAIN.getParam(), prop)); - setValue(ContextKey.COMPONENT, SwitcherUtils.resolveProperties(ContextKey.COMPONENT.getParam(), prop)); - setValue(ContextKey.ENVIRONMENT, getValueDefault(SwitcherUtils.resolveProperties(ContextKey.ENVIRONMENT.getParam(), prop), DEFAULT_ENV)); - setValue(ContextKey.SNAPSHOT_LOCATION, SwitcherUtils.resolveProperties(ContextKey.SNAPSHOT_LOCATION.getParam(), prop)); - setValue(ContextKey.SNAPSHOT_SKIP_VALIDATION, getBoolDefault(SwitcherUtils.resolveProperties(ContextKey.SNAPSHOT_SKIP_VALIDATION.getParam(), prop), false)); - setValue(ContextKey.SNAPSHOT_AUTO_LOAD, getBoolDefault(SwitcherUtils.resolveProperties(ContextKey.SNAPSHOT_AUTO_LOAD.getParam(), prop), false)); - setValue(ContextKey.SNAPSHOT_AUTO_UPDATE_INTERVAL, SwitcherUtils.resolveProperties(ContextKey.SNAPSHOT_AUTO_UPDATE_INTERVAL.getParam(), prop)); - setValue(ContextKey.SILENT_MODE, SwitcherUtils.resolveProperties(ContextKey.SILENT_MODE.getParam(), prop)); - setValue(ContextKey.LOCAL_MODE, getBoolDefault(SwitcherUtils.resolveProperties(ContextKey.LOCAL_MODE.getParam(), prop), false)); - setValue(ContextKey.CHECK_SWITCHERS, getBoolDefault(SwitcherUtils.resolveProperties(ContextKey.CHECK_SWITCHERS.getParam(), prop), false)); - setValue(ContextKey.RESTRICT_RELAY, getBoolDefault(SwitcherUtils.resolveProperties(ContextKey.RESTRICT_RELAY.getParam(), prop), true)); - setValue(ContextKey.REGEX_TIMEOUT, getIntDefault(SwitcherUtils.resolveProperties(ContextKey.REGEX_TIMEOUT.getParam(), prop), DEFAULT_REGEX_TIMEOUT)); - setValue(ContextKey.TRUSTSTORE_PATH, SwitcherUtils.resolveProperties(ContextKey.TRUSTSTORE_PATH.getParam(), prop)); - setValue(ContextKey.TRUSTSTORE_PASSWORD, SwitcherUtils.resolveProperties(ContextKey.TRUSTSTORE_PASSWORD.getParam(), prop)); - setValue(ContextKey.TIMEOUT_MS, getIntDefault(SwitcherUtils.resolveProperties(ContextKey.TIMEOUT_MS.getParam(), prop), DEFAULT_TIMEOUT)); - setValue(ContextKey.POOL_CONNECTION_SIZE, getIntDefault(SwitcherUtils.resolveProperties(ContextKey.POOL_CONNECTION_SIZE.getParam(), prop), DEFAULT_POOL_SIZE)); + setValue(ContextKey.CONTEXT_LOCATION, resolveProperties(ContextKey.CONTEXT_LOCATION.getParam(), prop)); + setValue(ContextKey.URL, resolveProperties(ContextKey.URL.getParam(), prop)); + setValue(ContextKey.APIKEY, resolveProperties(ContextKey.APIKEY.getParam(), prop)); + setValue(ContextKey.DOMAIN, resolveProperties(ContextKey.DOMAIN.getParam(), prop)); + setValue(ContextKey.COMPONENT, resolveProperties(ContextKey.COMPONENT.getParam(), prop)); + setValue(ContextKey.ENVIRONMENT, getValueDefault(resolveProperties(ContextKey.ENVIRONMENT.getParam(), prop), DEFAULT_ENV)); + setValue(ContextKey.SNAPSHOT_LOCATION, resolveProperties(ContextKey.SNAPSHOT_LOCATION.getParam(), prop)); + setValue(ContextKey.SNAPSHOT_SKIP_VALIDATION, getBoolDefault(resolveProperties(ContextKey.SNAPSHOT_SKIP_VALIDATION.getParam(), prop), false)); + setValue(ContextKey.SNAPSHOT_AUTO_LOAD, getBoolDefault(resolveProperties(ContextKey.SNAPSHOT_AUTO_LOAD.getParam(), prop), false)); + setValue(ContextKey.SNAPSHOT_AUTO_UPDATE_INTERVAL, resolveProperties(ContextKey.SNAPSHOT_AUTO_UPDATE_INTERVAL.getParam(), prop)); + setValue(ContextKey.SNAPSHOT_WATCHER, getBoolDefault(resolveProperties(ContextKey.SNAPSHOT_WATCHER.getParam(), prop), false)); + setValue(ContextKey.SILENT_MODE, resolveProperties(ContextKey.SILENT_MODE.getParam(), prop)); + setValue(ContextKey.LOCAL_MODE, getBoolDefault(resolveProperties(ContextKey.LOCAL_MODE.getParam(), prop), false)); + setValue(ContextKey.CHECK_SWITCHERS, getBoolDefault(resolveProperties(ContextKey.CHECK_SWITCHERS.getParam(), prop), false)); + setValue(ContextKey.RESTRICT_RELAY, getBoolDefault(resolveProperties(ContextKey.RESTRICT_RELAY.getParam(), prop), true)); + setValue(ContextKey.REGEX_TIMEOUT, getIntDefault(resolveProperties(ContextKey.REGEX_TIMEOUT.getParam(), prop), DEFAULT_REGEX_TIMEOUT)); + setValue(ContextKey.TRUSTSTORE_PATH, resolveProperties(ContextKey.TRUSTSTORE_PATH.getParam(), prop)); + setValue(ContextKey.TRUSTSTORE_PASSWORD, resolveProperties(ContextKey.TRUSTSTORE_PASSWORD.getParam(), prop)); + setValue(ContextKey.TIMEOUT_MS, getIntDefault(resolveProperties(ContextKey.TIMEOUT_MS.getParam(), prop), DEFAULT_TIMEOUT)); + setValue(ContextKey.POOL_CONNECTION_SIZE, getIntDefault(resolveProperties(ContextKey.POOL_CONNECTION_SIZE.getParam(), prop), DEFAULT_POOL_SIZE)); } @Override diff --git a/src/main/java/com/github/switcherapi/client/model/ContextKey.java b/src/main/java/com/github/switcherapi/client/model/ContextKey.java index a87f75f..1e1cca7 100644 --- a/src/main/java/com/github/switcherapi/client/model/ContextKey.java +++ b/src/main/java/com/github/switcherapi/client/model/ContextKey.java @@ -58,6 +58,11 @@ public enum ContextKey { * (String) Interval given to the library to update the snapshot */ SNAPSHOT_AUTO_UPDATE_INTERVAL("switcher.snapshot.updateinterval"), + + /** + * (boolean) Defines if the client will watch the snapshot file for changes and update the switchers accordingly. (default is false) + */ + SNAPSHOT_WATCHER("switcher.snapshot.watcher"), /** * (String) Defines if client will work in silent mode by specifying the time interval to retry diff --git a/src/test/java/com/github/switcherapi/client/utils/SnapshotTest.java b/src/test/java/com/github/switcherapi/client/utils/SnapshotTest.java new file mode 100644 index 0000000..419d502 --- /dev/null +++ b/src/test/java/com/github/switcherapi/client/utils/SnapshotTest.java @@ -0,0 +1,77 @@ +package com.github.switcherapi.client.utils; + +import com.github.switcherapi.SwitchersBase; +import com.github.switcherapi.client.model.criteria.Data; +import com.github.switcherapi.client.model.criteria.Domain; +import com.github.switcherapi.client.model.criteria.Snapshot; +import com.github.switcherapi.client.service.WorkerName; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Paths; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +abstract class SnapshotTest { + + private static final Logger logger = LoggerFactory.getLogger(SnapshotTest.class); + + protected static final String SNAPSHOTS_LOCAL = Paths.get(StringUtils.EMPTY).toAbsolutePath() + "/src/test/resources"; + + protected static void removeGeneratedFiles() throws IOException { + SwitchersBase.stopWatchingSnapshot(); + Files.deleteIfExists(Paths.get(SNAPSHOTS_LOCAL + "\\generated_watcher_default.json")); + } + + protected static void generateFixture() { + final Snapshot mockedSnapshot = new Snapshot(); + final Data data = new Data(); + data.setDomain(SnapshotLoader.loadSnapshot(SNAPSHOTS_LOCAL + "/snapshot_watcher.json")); + mockedSnapshot.setData(data); + + SnapshotLoader.saveSnapshot(mockedSnapshot, SNAPSHOTS_LOCAL, "generated_watcher_default"); + } + + protected void changeFixture() { + final Snapshot mockedSnapshot = new Snapshot(); + final Data data = new Data(); + data.setDomain(SnapshotLoader.loadSnapshot(SNAPSHOTS_LOCAL + "/snapshot_watcher.json")); + mockedSnapshot.setData(data); + + data.setDomain(new Domain( + data.getDomain().getName(), + data.getDomain().getDescription(), + !data.getDomain().isActivated(), + data.getDomain().getVersion(), + data.getDomain().getGroup())); + + final Gson gson = new GsonBuilder().setPrettyPrinting().create(); + writeFixture(gson.toJson(mockedSnapshot)); + } + + protected void writeFixture(String content) { + try ( + final FileWriter fileWriter = new FileWriter( + String.format("%s/%s.json", SNAPSHOTS_LOCAL, "generated_watcher_default")); + + final BufferedWriter bw = new BufferedWriter(fileWriter); + final PrintWriter wr = new PrintWriter(bw)) { + wr.write(content); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } + + protected void assertWorker(boolean exists) { + assertEquals(exists, Thread.getAllStackTraces().keySet().stream() + .anyMatch(t -> t.getName().equals(WorkerName.SNAPSHOT_WATCH_WORKER.toString()))); + } +} diff --git a/src/test/java/com/github/switcherapi/client/utils/SnapshotWatcherContextTest.java b/src/test/java/com/github/switcherapi/client/utils/SnapshotWatcherContextTest.java new file mode 100644 index 0000000..b44c7ba --- /dev/null +++ b/src/test/java/com/github/switcherapi/client/utils/SnapshotWatcherContextTest.java @@ -0,0 +1,69 @@ +package com.github.switcherapi.client.utils; + +import com.github.switcherapi.SwitchersBase; +import com.github.switcherapi.client.ContextBuilder; +import com.github.switcherapi.client.model.SwitcherRequest; +import com.github.switcherapi.fixture.CountDownHelper; +import org.junit.jupiter.api.*; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class SnapshotWatcherContextTest extends SnapshotTest { + + @BeforeAll + static void setupContext() throws IOException { + removeGeneratedFiles(); + generateFixture(); + + SwitchersBase.configure(ContextBuilder.builder(true) + .context(SwitchersBase.class.getCanonicalName()) + .environment("generated_watcher_default") + .snapshotLocation(SNAPSHOTS_LOCAL) + .snapshotWatcher(true) + .local(true)); + + SwitchersBase.initializeClient(); + } + + @AfterAll + static void tearDown() { + SwitchersBase.stopWatchingSnapshot(); + } + + @BeforeEach + void prepareTest() { + generateFixture(); + } + + @AfterEach + void afterEach() { + SwitchersBase.stopWatchingSnapshot(); + assertWorker(false); + } + + @Test + void shouldReloadDomainAfterChangingSnapshot() { + //verify that the worker is running + assertWorker(true); + + //given + SwitcherRequest switcher = SwitchersBase.getSwitcher(SwitchersBase.USECASE11); + + //initial value is true + assertTrue(switcher.isItOn()); + + CountDownHelper.wait(1); + + //when we change the fixture + this.changeFixture(); + + CountDownHelper.wait(2); + + //snapshot file updated - triggered domain reload + assertFalse(switcher.isItOn()); + } + +} diff --git a/src/test/java/com/github/switcherapi/client/utils/SnapshotWatcherTest.java b/src/test/java/com/github/switcherapi/client/utils/SnapshotWatcherTest.java index 5dbdc48..ae82a9b 100644 --- a/src/test/java/com/github/switcherapi/client/utils/SnapshotWatcherTest.java +++ b/src/test/java/com/github/switcherapi/client/utils/SnapshotWatcherTest.java @@ -3,36 +3,19 @@ import com.github.switcherapi.SwitchersBase; import com.github.switcherapi.client.ContextBuilder; import com.github.switcherapi.client.model.SwitcherRequest; -import com.github.switcherapi.client.model.criteria.Data; -import com.github.switcherapi.client.model.criteria.Domain; -import com.github.switcherapi.client.model.criteria.Snapshot; import com.github.switcherapi.fixture.CountDownHelper; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.io.BufferedWriter; -import java.io.FileWriter; import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.Paths; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -class SnapshotWatcherTest { - - private static final Logger logger = LoggerFactory.getLogger(SnapshotWatcherTest.class); - - private static final String SNAPSHOTS_LOCAL = Paths.get(StringUtils.EMPTY).toAbsolutePath() + "/src/test/resources"; - +class SnapshotWatcherTest extends SnapshotTest { + @BeforeAll static void setupContext() throws IOException { removeGeneratedFiles(); @@ -58,50 +41,6 @@ void prepareTest() { SwitchersBase.watchSnapshot(); } - static void removeGeneratedFiles() throws IOException { - SwitchersBase.stopWatchingSnapshot(); - Files.deleteIfExists(Paths.get(SNAPSHOTS_LOCAL + "\\generated_watcher_default.json")); - } - - static void generateFixture() { - final Snapshot mockedSnapshot = new Snapshot(); - final Data data = new Data(); - data.setDomain(SnapshotLoader.loadSnapshot(SNAPSHOTS_LOCAL + "/snapshot_watcher.json")); - mockedSnapshot.setData(data); - - SnapshotLoader.saveSnapshot(mockedSnapshot, SNAPSHOTS_LOCAL, "generated_watcher_default"); - } - - void changeFixture() { - final Snapshot mockedSnapshot = new Snapshot(); - final Data data = new Data(); - data.setDomain(SnapshotLoader.loadSnapshot(SNAPSHOTS_LOCAL + "/snapshot_watcher.json")); - mockedSnapshot.setData(data); - - data.setDomain(new Domain( - data.getDomain().getName(), - data.getDomain().getDescription(), - !data.getDomain().isActivated(), - data.getDomain().getVersion(), - data.getDomain().getGroup())); - - final Gson gson = new GsonBuilder().setPrettyPrinting().create(); - writeFixture(gson.toJson(mockedSnapshot)); - } - - void writeFixture(String content) { - try ( - final FileWriter fileWriter = new FileWriter( - String.format("%s/%s.json", SNAPSHOTS_LOCAL, "generated_watcher_default")); - - final BufferedWriter bw = new BufferedWriter(fileWriter); - final PrintWriter wr = new PrintWriter(bw)) { - wr.write(content); - } catch (Exception e) { - logger.error(e.getMessage(), e); - } - } - @Test void shouldNotReloadDomainAfterChangingSnapshot() { SwitcherRequest switcher = SwitchersBase.getSwitcher(SwitchersBase.USECASE11); diff --git a/src/test/java/com/github/switcherapi/client/utils/SnapshotWatcherWorkerTest.java b/src/test/java/com/github/switcherapi/client/utils/SnapshotWatcherWorkerTest.java index 950b571..102f23c 100644 --- a/src/test/java/com/github/switcherapi/client/utils/SnapshotWatcherWorkerTest.java +++ b/src/test/java/com/github/switcherapi/client/utils/SnapshotWatcherWorkerTest.java @@ -2,36 +2,21 @@ import com.github.switcherapi.SwitchersBase; import com.github.switcherapi.client.ContextBuilder; -import com.github.switcherapi.client.service.WorkerName; import com.github.switcherapi.fixture.CountDownHelper; -import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; -import java.nio.file.Paths; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class SnapshotWatcherWorkerTest { - - private static final String SNAPSHOTS_LOCAL = Paths.get(StringUtils.EMPTY).toAbsolutePath() + "/src/test/resources"; +class SnapshotWatcherWorkerTest extends SnapshotTest { @BeforeAll static void setupContext() { - SwitchersBase.configure(ContextBuilder.builder() + SwitchersBase.configure(ContextBuilder.builder(true) .context(SwitchersBase.class.getCanonicalName()) .snapshotLocation(SNAPSHOTS_LOCAL) .environment("default") - .silentMode(null) .local(true)); SwitchersBase.initializeClient(); - SwitchersBase.stopWatchingSnapshot(); - } - - void assertWorker(boolean exists) { - assertEquals(exists, Thread.getAllStackTraces().keySet().stream() - .anyMatch(t -> t.getName().equals(WorkerName.SNAPSHOT_WATCH_WORKER.toString()))); } @Test diff --git a/src/test/resources/switcherapi.properties b/src/test/resources/switcherapi.properties index 9215354..61028de 100644 --- a/src/test/resources/switcherapi.properties +++ b/src/test/resources/switcherapi.properties @@ -12,6 +12,7 @@ switcher.relay.restrict= switcher.snapshot.location= switcher.snapshot.auto= switcher.snapshot.updateinterval= +switcher.snapshot.watcher= switcher.silent= switcher.timeout= switcher.poolsize= \ No newline at end of file From d8562e44117f70336e1309adfaa861a256a7b35f Mon Sep 17 00:00:00 2001 From: petruki <31597636+petruki@users.noreply.github.com> Date: Sat, 21 Jun 2025 12:33:31 -0700 Subject: [PATCH 2/2] chore: bump test deps --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 2281843..e863f07 100644 --- a/pom.xml +++ b/pom.xml @@ -65,9 +65,9 @@ 5.0.0-alpha.16 - 5.13.0 + 5.13.1 1.9.1 - 1.13.0 + 1.13.1 3.14.0