Skip to content

Commit becad8d

Browse files
authored
Improved Snapshot scheduler and watcher APIs interface (#301)
* Improved Snapshot scheduler and watcher APIs interface * Refactored SwitcherWatcher to be used only with Local service * chore: removed unused import
1 parent 1478fe4 commit becad8d

10 files changed

Lines changed: 124 additions & 88 deletions

File tree

src/main/java/com/github/switcherapi/client/SnapshotCallback.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,24 @@
22

33
import com.github.switcherapi.client.utils.SwitcherUtils;
44
import org.apache.logging.log4j.LogManager;
5-
import org.apache.logging.log4j.Logger;
65

7-
public class SnapshotCallback {
8-
9-
private static final Logger logger = LogManager.getLogger(SnapshotCallback.class);
6+
public interface SnapshotCallback {
107

118
/**
129
* Callback method that will be invoked when the snapshot is updated
1310
*
1411
* @param version of the new snapshot
1512
*/
16-
public void onSnapshotUpdate(long version) {
17-
SwitcherUtils.debug(logger, "Snapshot updated: {}", version);
13+
default void onSnapshotUpdate(long version) {
14+
SwitcherUtils.debug(LogManager.getLogger(SnapshotCallback.class), "Snapshot updated: {}", version);
1815
}
1916

2017
/**
2118
* Callback method that will be invoked when the snapshot update fails
2219
*
2320
* @param e Exception
2421
*/
25-
public void onSnapshotUpdateError(Exception e) {
26-
SwitcherUtils.debug(logger, "Failed to update snapshot: {}", e.getMessage());
22+
default void onSnapshotUpdateError(Exception e) {
23+
SwitcherUtils.debug(LogManager.getLogger(SnapshotCallback.class), "Failed to update snapshot: {}", e.getMessage());
2724
}
2825
}

src/main/java/com/github/switcherapi/client/SwitcherContextBase.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ public static boolean scheduleSnapshotAutoUpdate(String intervalValue, SnapshotC
178178
}
179179

180180
final long interval = SwitcherUtils.getMillis(intervalValue);
181-
final SnapshotCallback callbackFinal = Optional.ofNullable(callback).orElse(new SnapshotCallback());
181+
final SnapshotCallback callbackFinal = Optional.ofNullable(callback).orElse(new SnapshotCallback() {});
182182
final Runnable runnableSnapshotValidate = () -> {
183183
try {
184184
if (validateSnapshot()) {
@@ -270,19 +270,31 @@ public static boolean validateSnapshot() {
270270
/**
271271
* Start watching snapshot files for modifications.<br>
272272
* When the file is modified the in-memory snapshot will reload
273+
*
274+
* <p>
275+
* (*) Requires client to use local settings
273276
*/
274277
public static void watchSnapshot() {
275-
watchSnapshot(new SnapshotEventHandler());
278+
watchSnapshot(new SnapshotEventHandler() {});
276279
}
277280

278281
/**
279282
* Start watching snapshot files for modifications.<br>
280283
* When the file is modified the in-memory snapshot will reload
284+
*
285+
* <p>
286+
* (*) Requires client to use local settings
281287
*
282288
* @param handler to notify snapshot change events
289+
* @throws SwitcherException if using remote service
283290
*/
284291
public static void watchSnapshot(SnapshotEventHandler handler) {
285-
SwitcherUtils.watchSnapshot(instance, handler);
292+
if (!(instance instanceof SwitcherLocalService)) {
293+
throw new SwitcherException("Cannot watch snapshot when using remote", new UnsupportedOperationException());
294+
}
295+
296+
SwitcherLocalService executorInstance = (SwitcherLocalService) instance;
297+
SwitcherUtils.watchSnapshot(executorInstance, handler);
286298
}
287299

288300
/**

src/main/java/com/github/switcherapi/client/SwitcherExecutor.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import com.github.switcherapi.client.model.criteria.Snapshot;
99
import com.github.switcherapi.client.model.response.CriteriaResponse;
1010
import com.github.switcherapi.client.service.remote.ClientRemote;
11-
import com.github.switcherapi.client.utils.SnapshotEventHandler;
1211
import com.github.switcherapi.client.utils.SnapshotLoader;
1312
import com.github.switcherapi.client.utils.SwitcherUtils;
1413
import com.google.gson.Gson;
@@ -59,16 +58,6 @@ public abstract class SwitcherExecutor {
5958
* @param switchers To be validated
6059
*/
6160
public abstract void checkSwitchers(final Set<String> switchers);
62-
63-
/**
64-
* Update in-memory snapshot.
65-
*
66-
* @param snapshotFile Path location
67-
* @param handler to notify snapshot change events
68-
*
69-
* @return true if valid change
70-
*/
71-
public abstract boolean notifyChange(final String snapshotFile, SnapshotEventHandler handler);
7261

7362
/**
7463
* Retrieve local snapshot version

src/main/java/com/github/switcherapi/client/service/local/SwitcherLocalService.java

Lines changed: 38 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,44 @@ public void init() {
6262
}
6363
}
6464
}
65+
66+
/**
67+
* Update in-memory snapshot.
68+
*
69+
* @param snapshotFile Path location
70+
* @param handler to notify snapshot change events
71+
*
72+
* @return true if valid change
73+
*/
74+
public boolean notifyChange(final String snapshotFile, SnapshotEventHandler handler) {
75+
final String environment = SwitcherContextBase.contextStr(ContextKey.ENVIRONMENT);
76+
final String snapshotLocation = SwitcherContextBase.contextStr(ContextKey.SNAPSHOT_LOCATION);
77+
78+
try {
79+
if (snapshotFile.equals(String.format("%s.json", environment))) {
80+
SwitcherUtils.debug(logger, "Updating domain");
81+
82+
this.domain = SnapshotLoader.loadSnapshot(snapshotLocation, environment);
83+
handler.onSuccess();
84+
}
85+
} catch (SwitcherSnapshotLoadException | IOException e) {
86+
handler.onError(new SwitcherException(e.getMessage(), e));
87+
logger.error(e);
88+
return false;
89+
}
90+
91+
return true;
92+
}
93+
94+
/**
95+
* Update in-memory snapshot.
96+
*
97+
* @param snapshotFile Path location
98+
* @return true if valid change
99+
*/
100+
public boolean notifyChange(final String snapshotFile) {
101+
return this.notifyChange(snapshotFile, new SnapshotEventHandler() {});
102+
}
65103

66104
@Override
67105
public CriteriaResponse executeCriteria(final Switcher switcher) {
@@ -111,27 +149,6 @@ public void checkSwitchers(final Set<String> switchers) {
111149
throw new SwitchersValidationException(response.toString());
112150
}
113151
}
114-
115-
@Override
116-
public boolean notifyChange(final String snapshotFile, SnapshotEventHandler handler) {
117-
final String environment = SwitcherContextBase.contextStr(ContextKey.ENVIRONMENT);
118-
final String snapshotLocation = SwitcherContextBase.contextStr(ContextKey.SNAPSHOT_LOCATION);
119-
120-
try {
121-
if (snapshotFile.equals(String.format("%s.json", environment))) {
122-
SwitcherUtils.debug(logger, "Updating domain");
123-
124-
this.domain = SnapshotLoader.loadSnapshot(snapshotLocation, environment);
125-
handler.onSuccess();
126-
}
127-
} catch (SwitcherSnapshotLoadException | IOException e) {
128-
handler.onError(new SwitcherException(e.getMessage(), e));
129-
logger.error(e);
130-
return false;
131-
}
132-
133-
return true;
134-
}
135152

136153
@Override
137154
public long getSnapshotVersion() {

src/main/java/com/github/switcherapi/client/service/remote/SwitcherRemoteService.java

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
package com.github.switcherapi.client.service.remote;
22

3-
import java.util.Arrays;
4-
import java.util.Set;
5-
6-
import com.github.switcherapi.client.utils.SwitcherUtils;
7-
import org.apache.commons.lang3.StringUtils;
8-
import org.apache.logging.log4j.LogManager;
9-
import org.apache.logging.log4j.Logger;
10-
113
import com.github.switcherapi.client.SwitcherContextBase;
124
import com.github.switcherapi.client.SwitcherExecutor;
135
import com.github.switcherapi.client.exception.SwitcherRemoteException;
@@ -17,7 +9,13 @@
179
import com.github.switcherapi.client.model.criteria.SwitchersCheck;
1810
import com.github.switcherapi.client.model.response.CriteriaResponse;
1911
import com.github.switcherapi.client.service.local.SwitcherLocalService;
20-
import com.github.switcherapi.client.utils.SnapshotEventHandler;
12+
import com.github.switcherapi.client.utils.SwitcherUtils;
13+
import org.apache.commons.lang3.StringUtils;
14+
import org.apache.logging.log4j.LogManager;
15+
import org.apache.logging.log4j.Logger;
16+
17+
import java.util.Arrays;
18+
import java.util.Set;
2119

2220
/**
2321
* @author Roger Floriano (petruki)
@@ -95,11 +93,6 @@ public void checkSwitchers(final Set<String> switchers) {
9593
throw new SwitchersValidationException(Arrays.toString(response.getNotFound()));
9694
}
9795
}
98-
99-
@Override
100-
public boolean notifyChange(String snapshotFile, SnapshotEventHandler handler) {
101-
return this.switcherLocal.notifyChange(snapshotFile, handler);
102-
}
10396

10497
@Override
10598
public long getSnapshotVersion() {
Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package com.github.switcherapi.client.utils;
22

3-
import org.apache.logging.log4j.LogManager;
4-
import org.apache.logging.log4j.Logger;
5-
63
import com.github.switcherapi.client.exception.SwitcherException;
4+
import org.apache.logging.log4j.LogManager;
75

86
/**
97
* Access snapshot event handler when a file is modified.<br>
@@ -12,16 +10,22 @@
1210
* @author Roger Floriano (petruki)
1311
* @since 2022-06-29
1412
*/
15-
public class SnapshotEventHandler {
16-
17-
private static final Logger logger = LogManager.getLogger(SnapshotEventHandler.class);
18-
19-
public void onSuccess() {
20-
SwitcherUtils.debug(logger, "Snapshot has been changed");
13+
public interface SnapshotEventHandler {
14+
15+
/**
16+
* Callback method that will be invoked when the snapshot is updated
17+
*/
18+
default void onSuccess() {
19+
SwitcherUtils.debug(LogManager.getLogger(SnapshotEventHandler.class), "Snapshot has been changed");
2120
}
22-
23-
public void onError(SwitcherException exception) {
24-
logger.error(exception);
21+
22+
/**
23+
* Callback method that will be invoked when the snapshot update fails
24+
*
25+
* @param exception Exception
26+
*/
27+
default void onError(SwitcherException exception) {
28+
LogManager.getLogger(SnapshotEventHandler.class).error(exception);
2529
}
2630

2731
}

src/main/java/com/github/switcherapi/client/utils/SnapshotWatcher.java

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,17 @@
11
package com.github.switcherapi.client.utils;
22

3-
import java.io.IOException;
4-
import java.nio.file.ClosedWatchServiceException;
5-
import java.nio.file.FileSystems;
6-
import java.nio.file.Path;
7-
import java.nio.file.Paths;
8-
import java.nio.file.StandardWatchEventKinds;
9-
import java.nio.file.WatchEvent;
10-
import java.nio.file.WatchKey;
11-
import java.nio.file.WatchService;
12-
3+
import com.github.switcherapi.client.SwitcherContextBase;
4+
import com.github.switcherapi.client.model.ContextKey;
5+
import com.github.switcherapi.client.service.local.SwitcherLocalService;
136
import org.apache.logging.log4j.LogManager;
147
import org.apache.logging.log4j.Logger;
158

16-
import com.github.switcherapi.client.SwitcherContextBase;
17-
import com.github.switcherapi.client.SwitcherExecutor;
18-
import com.github.switcherapi.client.model.ContextKey;
9+
import java.io.IOException;
10+
import java.nio.file.*;
1911

2012
/**
13+
* SnapshotWatcher runs in a separate thread to watch for changes in the snapshot file.
14+
*
2115
* @author Roger Floriano (petruki)
2216
* @since 2020-05-13
2317
*/
@@ -29,9 +23,9 @@ public class SnapshotWatcher implements Runnable {
2923

3024
private WatchService watcher;
3125

32-
private SwitcherExecutor executorInstance;
26+
private SwitcherLocalService executorInstance;
3327

34-
public SnapshotWatcher(final SwitcherExecutor executorInstance, SnapshotEventHandler handler) {
28+
public SnapshotWatcher(final SwitcherLocalService executorInstance, SnapshotEventHandler handler) {
3529
this.executorInstance = executorInstance;
3630
this.handler = handler;
3731
}

src/main/java/com/github/switcherapi/client/utils/SwitcherUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package com.github.switcherapi.client.utils;
22

3-
import com.github.switcherapi.client.SwitcherExecutor;
43
import com.github.switcherapi.client.exception.SwitcherContextException;
54
import com.github.switcherapi.client.exception.SwitcherInvalidDateTimeArgumentException;
65
import com.github.switcherapi.client.model.ContextKey;
76
import com.github.switcherapi.client.service.WorkerName;
7+
import com.github.switcherapi.client.service.local.SwitcherLocalService;
88
import com.google.gson.JsonElement;
99
import com.google.gson.JsonObject;
1010
import com.google.gson.JsonParser;
@@ -141,7 +141,7 @@ public static Set<String> payloadReader(String jsonStr, String prevKey) {
141141
* @param executorInstance of a Remote or Local Switcher
142142
* @param handler to notify snapshot change events
143143
*/
144-
public static void watchSnapshot(final SwitcherExecutor executorInstance, SnapshotEventHandler handler) {
144+
public static void watchSnapshot(final SwitcherLocalService executorInstance, SnapshotEventHandler handler) {
145145
if (watcher == null) {
146146
watcher = new SnapshotWatcher(executorInstance, handler);
147147
}

src/test/java/com/github/switcherapi/client/service/local/SwitcherLocalServiceTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,15 @@ void shouldNotifyWithError() {
3737
SwitchersBase.configure(ContextBuilder.builder()
3838
.environment("defect_default"));
3939

40-
assertFalse(service.notifyChange("defect_default.json", new SnapshotEventHandler()));
40+
assertFalse(service.notifyChange("defect_default.json"));
4141
}
4242

4343
@Test
4444
void shouldNotifyWithSuccess() {
4545
SwitchersBase.configure(ContextBuilder.builder()
4646
.environment("snapshot_watcher"));
4747

48-
assertTrue(service.notifyChange("snapshot_watcher.json", new SnapshotEventHandler()));
48+
assertTrue(service.notifyChange("snapshot_watcher.json"));
4949
}
5050

5151
@Test
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.github.switcherapi.client.utils;
2+
3+
import com.github.switcherapi.SwitchersBase;
4+
import com.github.switcherapi.client.ContextBuilder;
5+
import com.github.switcherapi.client.exception.SwitcherException;
6+
import org.junit.jupiter.api.Test;
7+
8+
import static org.junit.jupiter.api.Assertions.assertEquals;
9+
import static org.junit.jupiter.api.Assertions.assertThrows;
10+
11+
class SnapshotWatcherErrorTest {
12+
13+
@Test
14+
void shouldNotWatchSnapshotWhenRemote() {
15+
//given
16+
SwitchersBase.configure(ContextBuilder.builder()
17+
.contextLocation(SwitchersBase.class.getCanonicalName())
18+
.url("https://api.switcherapi.com")
19+
.apiKey("[API_KEY]")
20+
.domain("Test")
21+
.component("switcher-test")
22+
.local(false));
23+
24+
SwitchersBase.initializeClient();
25+
26+
//test
27+
SwitcherException exception = assertThrows(SwitcherException.class, SwitchersBase::watchSnapshot);
28+
assertEquals("Something went wrong: Cannot watch snapshot when using remote", exception.getMessage());
29+
}
30+
}

0 commit comments

Comments
 (0)