diff --git a/build.gradle b/build.gradle index ea1e46a..ae2597d 100644 --- a/build.gradle +++ b/build.gradle @@ -5,8 +5,13 @@ plugins { id "com.diffplug.spotless" version "6.13.0" } +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + group = 'cloud.eppo' -version = '3.0.0-SNAPSHOT' +version = '3.0.1-SNAPSHOT' ext.isReleaseVersion = !version.endsWith("SNAPSHOT") import org.apache.tools.ant.filters.ReplaceTokens @@ -25,10 +30,11 @@ repositories { } dependencies { - implementation 'cloud.eppo:sdk-common-jvm:3.0.1-SNAPSHOT' + // Re-export classes and interfaces that will be used upstream + api 'cloud.eppo:sdk-common-jvm:3.0.2-SNAPSHOT' + implementation 'com.github.zafarkhaja:java-semver:0.10.2' implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.1' - implementation 'org.apache.httpcomponents:httpclient:4.5.14' implementation 'org.ehcache:ehcache:3.10.8' implementation 'org.slf4j:slf4j-api:2.0.13' // Logback classic 1.3.x is compatible with java 8 @@ -128,16 +134,18 @@ publishing { } } -signing { - sign publishing.publications.mavenJava - if (System.env['CI']) { - useInMemoryPgpKeys(System.env.GPG_PRIVATE_KEY, System.env.GPG_PASSPHRASE) +if (!project.gradle.startParameter.taskNames.contains('publishToMavenLocal')) { + signing { + sign publishing.publications.mavenJava + if (System.env['CI']) { + useInMemoryPgpKeys(System.env.GPG_PRIVATE_KEY, System.env.GPG_PASSPHRASE) + } } } - javadoc { if (JavaVersion.current().isJava9Compatible()) { options.addBooleanOption('html5', true) } + options.addStringOption('Xdoclint:none', '-quiet') } diff --git a/src/main/java/com/eppo/sdk/EppoClient.java b/src/main/java/com/eppo/sdk/EppoClient.java index 78b0609..d3509a2 100644 --- a/src/main/java/com/eppo/sdk/EppoClient.java +++ b/src/main/java/com/eppo/sdk/EppoClient.java @@ -9,6 +9,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * Class used to ingest and use the flag and bandit configurations retrieved from Eppo This class + * uses the Singleton pattern. First the singleton must be initialized via it's Builder's + * buildAndInit() method. Then call getInstance() to access the singleton and call methods to get + * assignments and bandit actions. + */ public class EppoClient extends BaseEppoClient { private static final Logger log = LoggerFactory.getLogger(EppoClient.class); @@ -40,63 +46,92 @@ private EppoClient( apiKey, host, sdkName, sdkVersion, assignmentLogger, banditLogger, isGracefulModel, false); } + /** Stops the client from polling Eppo for updated flag and bandit configurations */ public static void stopPolling() { if (pollTimer != null) { pollTimer.cancel(); } } + /** Builder pattern to initialize the EppoClient singleton */ public static class Builder { private String apiKey; - private String host = DEFAULT_HOST; private AssignmentLogger assignmentLogger; private BanditLogger banditLogger; private boolean isGracefulMode = DEFAULT_IS_GRACEFUL_MODE; private boolean forceReinitialize = DEFAULT_FORCE_REINITIALIZE; private long pollingIntervalMs = DEFAULT_POLLING_INTERVAL_MS; + private String host = DEFAULT_HOST; + /** Sets the API Key--created within the eppo application--to use. This is required. */ public Builder apiKey(String apiKey) { this.apiKey = apiKey; return this; } - public Builder host(String host) { - this.host = host; - return this; - } - + /** + * Assignment logger to use to record when variations were assigned. This is needed if you want + * Eppo to analyze experiments controlled by flags. + */ public Builder assignmentLogger(AssignmentLogger assignmentLogger) { this.assignmentLogger = assignmentLogger; return this; } + /** + * Bandit logger to use to record when a bandit has assigned an action. This is needed if you + * are using contextual multi-armed bandits. + */ public Builder banditLogger(BanditLogger banditLogger) { this.banditLogger = banditLogger; return this; } + /** + * Sets the initial graceful mode of the client. When on (which is the default), flag evaluation + * errors will be caught, and the default value returned. When off, the errors will be rethrown. + */ public Builder isGracefulMode(boolean isGracefulMode) { this.isGracefulMode = isGracefulMode; return this; } + /** + * Sets whether the singleton client should be recreated if one already has been. fetch an + * updated configuration. If true, a new client will be instantiated and a new fetch for + * configurations will be performed. If false (which is the default), initialization will be + * ignored and the previously initialized client will be used. + */ public Builder forceReinitialize(boolean forceReinitialize) { this.forceReinitialize = forceReinitialize; return this; } + /** + * Sets how often the client should check for updated configurations, in milliseconds. The + * default is 30,000 (poll every 30 seconds). + */ public Builder pollingIntervalMs(long pollingIntervalMs) { this.pollingIntervalMs = pollingIntervalMs; return this; } + /** + * Overrides the host from where it fetches configurations. This typically should not be + * explicitly set so that the default of the Fastly CDN is used. + */ + public Builder host(String host) { + this.host = host; + return this; + } + public EppoClient buildAndInit() { AppDetails appDetails = AppDetails.getInstance(); String sdkName = appDetails.getName(); String sdkVersion = appDetails.getVersion(); if (instance != null) { - if (forceReinitialize) { // TODO: unit test this + if (forceReinitialize) { log.warn( "Eppo SDK is already initialized, reinitializing since forceReinitialize is true"); } else { diff --git a/src/test/java/com/eppo/sdk/EppoClientTest.java b/src/test/java/com/eppo/sdk/EppoClientTest.java index 7f7ef12..d71a14f 100644 --- a/src/test/java/com/eppo/sdk/EppoClientTest.java +++ b/src/test/java/com/eppo/sdk/EppoClientTest.java @@ -10,6 +10,9 @@ import cloud.eppo.BaseEppoClient; import cloud.eppo.EppoHttpClient; +import cloud.eppo.api.Attributes; +import cloud.eppo.api.BanditActions; +import cloud.eppo.api.BanditResult; import cloud.eppo.helpers.AssignmentTestCase; import cloud.eppo.helpers.BanditTestCase; import cloud.eppo.helpers.TestUtils; @@ -17,7 +20,6 @@ import cloud.eppo.logging.AssignmentLogger; import cloud.eppo.logging.BanditAssignment; import cloud.eppo.logging.BanditLogger; -import cloud.eppo.ufc.dto.*; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; import com.github.tomakehurst.wiremock.junit5.WireMockExtension;