Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<groupId>com.github.switcherapi</groupId>
<artifactId>switcher-client</artifactId>
<packaging>jar</packaging>
<version>2.0.4</version>
<version>2.0.5-SNAPSHOT</version>

<name>Switcher Client</name>
<description>Switcher Client SDK for working with Switcher API</description>
Expand Down
31 changes: 31 additions & 0 deletions src/main/java/com/github/switcherapi/client/SnapshotCallback.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.github.switcherapi.client;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class SnapshotCallback {

private static final Logger logger = LogManager.getLogger(SnapshotCallback.class);

/**
* Callback method that will be invoked when the snapshot is updated
*
* @param version of the new snapshot
*/
public void onSnapshotUpdate(long version) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Snapshot updated: %s", version));
}
}

/**
* Callback method that will be invoked when the snapshot update fails
*
* @param e Exception
*/
public void onSnapshotUpdateError(Exception e) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Failed to update snapshot: %s", e.getMessage()));
}
}
}
35 changes: 7 additions & 28 deletions src/main/java/com/github/switcherapi/client/SwitcherContext.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.github.switcherapi.client;

import com.github.switcherapi.client.exception.SwitcherKeyNotFoundException;
import com.github.switcherapi.client.exception.SwitchersValidationException;
import com.github.switcherapi.client.model.ContextKey;
import com.github.switcherapi.client.model.Switcher;

Expand Down Expand Up @@ -37,20 +35,14 @@ public static void loadProperties() {
}

/**
* Initialize Switcher Client
* {@link SwitcherContextBase#initializeClient()}
*/
public static void initializeClient() {
SwitcherContextBase.initializeClient();
}

/**
* Return a ready-to-use Switcher that will invoke the criteria configured into the Switcher API or Snapshot
*
* @param key name of the key created
* @param keepEntries when true it will return a cached Switcher with all parameters used before
*
* @return a ready to use Switcher
* @throws SwitcherKeyNotFoundException in case the key was not properly loaded
* {@link SwitcherContextBase#getSwitcher(String, boolean)}
*/
public static Switcher getSwitcher(String key, boolean keepEntries) {
return SwitcherContextBase.getSwitcher(key, keepEntries);
Expand All @@ -67,19 +59,14 @@ public static Switcher getSwitcher(String key) {
}

/**
* Validate and update local snapshot file.<br>
* It requires offline mode or SwitcherContextParam.SNAPSHOT_LOCATION configured
*
* @return true if validation was performed
* {@link SwitcherContextBase#validateSnapshot()}
*/
public static boolean validateSnapshot() {
return SwitcherContextBase.validateSnapshot();
}

/**
* Executes smoke test against the API to verify if all Switchers are properly configured
*
* @throws SwitchersValidationException when one or more Switcher Key is not found
* {@link SwitcherContextBase#checkSwitchers()}
*/
public static void checkSwitchers() {
SwitcherContextBase.checkSwitchers();
Expand All @@ -95,29 +82,21 @@ public static long getSnapshotVersion() {
}

/**
* Retrieve string context parameter based on contextKey
*
* @param contextKey to be retrieved
* @return Value configured for the context parameter
* {@link SwitcherContextBase#contextStr(ContextKey)}
*/
public static String contextStr(ContextKey contextKey) {
return SwitcherContextBase.contextStr(contextKey);
}

/**
* Retrieve boolean context parameter based on contextKey
*
* @param contextKey to be retrieved
* @return Value configured for the context parameter
* {@link SwitcherContextBase#contextBol(ContextKey)}
*/
public static boolean contextBol(ContextKey contextKey) {
return SwitcherContextBase.contextBol(contextKey);
}

/**
* Fluent builder to configure the Switcher Context
*
* @param builder specification to be applied
* {@link SwitcherContextBase#configure(ContextBuilder)}
*/
public static void configure(ContextBuilder builder) {
SwitcherContextBase.configure(builder);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public static void initializeClient() {
}

loadSwitchers();
scheduleSnapshotAutoUpdate();
scheduleSnapshotAutoUpdate(switcherProperties.getSnapshotAutoUpdateInterval(), null);
ContextBuilder.preConfigure(switcherProperties);
}

Expand Down Expand Up @@ -163,15 +163,28 @@ private static void loadSwitchers() {
}

/**
* Configure worker for Scheduled Snapshot Auto Update based on the interval provided at
* the configuration "switcher.snapshot.updateinterval"
* Schedule a task to update the snapshot automatically.<br>
* The task will be executed in a single thread executor service.
*
* @param intervalValue to be used for the update (e.g. 5s, 1m, 1h, 1d)
* @param callback to be invoked when the snapshot is updated or when an error occurs
*/
private static void scheduleSnapshotAutoUpdate() {
if (StringUtils.isBlank(switcherProperties.getSnapshotAutoUpdateInterval()))
public static void scheduleSnapshotAutoUpdate(String intervalValue, SnapshotCallback callback) {
if (StringUtils.isBlank(intervalValue))
return;

final long interval = SwitcherUtils.getMillis(switcherProperties.getSnapshotAutoUpdateInterval());
final Runnable runnableSnapshotValidate = SwitcherContextBase::validateSnapshot;
final long interval = SwitcherUtils.getMillis(intervalValue);
final SnapshotCallback callbackFinal = Optional.ofNullable(callback).orElse(new SnapshotCallback());
final Runnable runnableSnapshotValidate = () -> {
try {
if (validateSnapshot()) {
callbackFinal.onSnapshotUpdate(instance.getSnapshotVersion());
}
} catch (Exception e) {
logger.error(e.getMessage());
callbackFinal.onSnapshotUpdateError(e);
}
};

initExecutorService();
scheduledExecutorService.scheduleAtFixedRate(runnableSnapshotValidate, 0, interval, TimeUnit.MILLISECONDS);
Expand Down Expand Up @@ -223,20 +236,17 @@ public static Switcher getSwitcher(String key) {
}

/**
* Validate and update local snapshot file.<br>
* It requires offline mode or SwitcherContextParam.SNAPSHOT_LOCATION configured
* Validate if the snapshot version is the same as the one in the API.<br>
* If the version is different, it will update the snapshot in memory.
*
* @return true if validation was performed
* @return true if snapshot was updated
*/
public static boolean validateSnapshot() {
if (switcherProperties.isSnapshotSkipValidation()) {
if (switcherProperties.isSnapshotSkipValidation() || instance.checkSnapshotVersion()) {
return false;
}

if (!instance.checkSnapshotVersion()) {
instance.updateSnapshot();
}


instance.updateSnapshot();
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ void shouldValidateAndNotUpdateSnapshot() {

assertDoesNotThrow(() -> {
Switchers.initializeClient();
assertTrue(Switchers.validateSnapshot());
assertFalse(Switchers.validateSnapshot());
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,34 @@ void shouldUpdateSnapshot_online_inMemory() {
assertEquals(2, Switchers.getSnapshotVersion());
}

@Test
@Order(5)
void shouldNotKillThread_whenAPI_wentOffline() {
//given
givenResponse(generateMockAuth()); //auth
givenResponse(generateSnapshotResponse("default_outdated.json")); //graphql

//that
Switchers.configure(ContextBuilder.builder()
.url(String.format("http://localhost:%s", mockBackEnd.getPort()))
.snapshotLocation(null)
.environment("generated_mock_default_6")
.offlineMode(true)
.snapshotAutoLoad(true)
.snapshotAutoUpdateInterval("1s"));

Switchers.initializeClient();
assertEquals(1, Switchers.getSnapshotVersion());

CountDownHelper.wait(1);

//given - API is online again
givenResponse(generateCheckSnapshotVersionResponse(Boolean.toString(false))); //criteria/snapshot_check
givenResponse(generateSnapshotResponse("default.json")); //graphql

//test
CountDownHelper.wait(2);
assertEquals(2, Switchers.getSnapshotVersion());
}

}