Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ java {
}

group = 'cloud.eppo'
version = '4.0.1-SNAPSHOT'
version = '5.0.0'
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

major bump as the static method stopPolling has been removed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ‘ Makes sense!

ext.isReleaseVersion = !version.endsWith("SNAPSHOT")

import org.apache.tools.ant.filters.ReplaceTokens
Expand All @@ -30,7 +30,7 @@ repositories {
}

dependencies {
api 'cloud.eppo:sdk-common-jvm:3.6.0'
api 'cloud.eppo:sdk-common-jvm:3.8.0'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ“ˆ


implementation 'com.github.zafarkhaja:java-semver:0.10.2'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.18.2'
Expand Down
34 changes: 9 additions & 25 deletions src/main/java/cloud/eppo/EppoClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import cloud.eppo.cache.LRUInMemoryAssignmentCache;
import cloud.eppo.logging.AssignmentLogger;
import cloud.eppo.logging.BanditLogger;
import java.util.Timer;
import java.util.concurrent.TimeUnit;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
Expand All @@ -26,7 +25,6 @@ public class EppoClient extends BaseEppoClient {
private static final long DEFAULT_JITTER_INTERVAL_RATIO = 10;

private static EppoClient instance;
private static Timer pollTimer;

public static EppoClient getInstance() {
if (instance == null) {
Expand Down Expand Up @@ -62,13 +60,6 @@ private EppoClient(
banditAssignmentCache);
}

/** Stops the client from polling Eppo for updated flag and bandit configurations */
public static void stopPolling() {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stopPolling is now a method on the EppoClient instance, so it can't be overridden by a static method.
I do not expect this will be a high friction change for developers, if a change is required at all (fewer devs will use stopPolling than will use startPolling).

if (pollTimer != null) {
pollTimer.cancel();
}
}

/** Builder pattern to initialize the EppoClient singleton */
public static class Builder {
private String apiKey;
Expand Down Expand Up @@ -163,6 +154,8 @@ public EppoClient buildAndInit() {
String sdkVersion = appDetails.getVersion();

if (instance != null) {
// Stop any active polling.
instance.stopPolling();
if (forceReinitialize) {
log.warn(
"Eppo SDK is already initialized, reinitializing since forceReinitialize is true");
Expand All @@ -185,22 +178,13 @@ public EppoClient buildAndInit() {
assignmentCache,
banditAssignmentCache);

// Stop any active polling
stopPolling();

// Set up polling for experiment configurations
pollTimer = new Timer(true);
FetchConfigurationsTask fetchConfigurationsTask =
new FetchConfigurationsTask(
() -> instance.loadConfiguration(),
pollTimer,
pollingIntervalMs,
pollingIntervalMs / DEFAULT_JITTER_INTERVAL_RATIO);

// Kick off the first fetch
// Graceful mode is implicit here because `FetchConfigurationsTask` catches and logs errors
// without rethrowing.
fetchConfigurationsTask.run();
// Fetch first configuration
instance.loadConfiguration();

// start polling, if enabled.
if (pollingIntervalMs > 0) {
instance.startPolling(pollingIntervalMs, pollingIntervalMs / DEFAULT_JITTER_INTERVAL_RATIO);
}

return instance;
}
Expand Down
19 changes: 17 additions & 2 deletions src/test/java/cloud/eppo/EppoClientTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
import cloud.eppo.api.Attributes;
import cloud.eppo.api.BanditActions;
import cloud.eppo.api.BanditResult;
import cloud.eppo.api.Configuration;
import cloud.eppo.helpers.AssignmentTestCase;
import cloud.eppo.helpers.BanditTestCase;
import cloud.eppo.helpers.TestUtils;
import cloud.eppo.logging.Assignment;
import cloud.eppo.logging.AssignmentLogger;
import cloud.eppo.logging.BanditAssignment;
import cloud.eppo.logging.BanditLogger;
import cloud.eppo.ufc.dto.VariationType;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
Expand Down Expand Up @@ -91,7 +93,11 @@ private static String readConfig(String jsonToReturnFilePath) {
@AfterEach
public void cleanUp() {
TestUtils.setBaseClientHttpClientOverrideField(null);
EppoClient.stopPolling();
try {
EppoClient.getInstance().stopPolling();
} catch (IllegalStateException ex) {
// pass: Indicates that the singleton Eppo Client has not yet been initialized.
}
}

@AfterAll
Expand Down Expand Up @@ -232,7 +238,7 @@ public void testPolling() {
// Now, the method should have been called twice
verify(httpClientSpy, times(2)).get(anyString());

EppoClient.stopPolling();
EppoClient.getInstance().stopPolling();
sleepUninterruptedly(25);

// No more calls since stopped
Expand All @@ -257,6 +263,15 @@ public void testClientMakesDefaultAssignmentsAfterFailingToInitialize() {
}
}

@Test
public void testGetConfiguration() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ’ͺ

EppoClient eppoClient = initClient(DUMMY_FLAG_API_KEY);
Configuration configuration = eppoClient.getConfiguration();
assertNotNull(configuration);
assertNotNull(configuration.getFlag("numeric_flag"));
assertEquals(VariationType.NUMERIC, configuration.getFlagType("numeric_flag"));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ”₯

}

public static void mockHttpError() {
// Create a mock instance of EppoHttpClient
EppoHttpClient mockHttpClient = mock(EppoHttpClient.class);
Expand Down