Skip to content

Conversation

aarsilv
Copy link
Collaborator

@aarsilv aarsilv commented Aug 13, 2024

Eppo Internal:
🎟️ Ticket: FF-2842 - Java SDK UFC and Bandits Tests Passing
πŸ‘―β€β™€οΈ Related PR: sdk-common-jdk #29

This updates the Java SDK to leverage the shared common SDK (sdk-common-jdk), which upgrades it to using the Universal Flag Configuration (UFC) files.

The tests for EppoClient have been updated to cover:

  • Shared UFC test cases (from sdk-test-data)
  • Shared Bandit test cases (from sdk-test-data)
  • Loggers
  • Graceful Mode (or not)
  • Forcing reinitialization (or not)
  • Polling

Note: this won't successfully run integration tests until the common SDK changes have been merged and published. However, using the updated common repository published to a local maven repository, the tests pass:
image

@@ -1,5 +1,7 @@
src/test/resources/shared
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

putting the shared test files in the same place the shared common repository does for consistency and to make it easier to reuse testing tools

testImplementation platform('org.junit:junit-bom:5.10.2')
testImplementation 'org.junit.jupiter:junit-jupiter'
testImplementation 'com.github.tomakehurst:wiremock-jre8:2.35.2'
testImplementation 'org.mockito:mockito-core:4.11.0'
testImplementation 'com.squareup.okhttp3:okhttp:4.9.1'
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Needed to mock stuff regarding Reponse

import java.util.*;
import java.util.stream.Collectors;
import org.ehcache.Cache;
import cloud.eppo.BaseEppoClient;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It's not worth comparing the diff here, just look at the new (green) code to see what's going on. I'll add comments to help guide.

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EppoClient {
public class EppoClient extends BaseEppoClient {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The way things worked out, I opting for inheritance. My first pass did composition but then getInstance() was returning BaseEppoClient and there were some protected things (like loadConfigurations() I wanted to be able to leverage but not exposed outside of this class.

It may seem like an odd pattern choice (for now), as the only thing really overridden is the constructor. However it works well and I think it will be more useful for android when we start dealing with thing like caching.

}

/** This function is used to get assignment Value */
protected Optional<EppoValue> getAssignmentValue(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

All getAssignment()-like methods now live in BaseEppoClient

InputValidator.validateNotBlank(subjectKey, "Invalid argument: subjectKey cannot be blank");
InputValidator.validateNotBlank(flagKey, "Invalid argument: flagKey cannot be blank");
private static EppoClient instance;
private static Timer pollTimer;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The poller made static so that it is a singleton as well, and we don't have renegade timers everywhere. Also so it can easily be stopped (useful for tests)

subjectCategoricalAttributes,
actionNumericAttributes,
actionCategoricalAttributes));
public Builder forceReinitialize(boolean forceReinitialize) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Latest and greatest from our JavaScript repository πŸ“ˆ

* @param actionAttributes attributes associated with the given action
* @return null if no exception was encountered by logging; otherwise, the encountered exception
*/
public Exception logNonBanditAction(
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We decided to ax this functionality πŸͺ“ The juice was not worth the squeeze

@@ -7,38 +7,31 @@

public class FetchConfigurationsTask extends TimerTask {
private static final Logger log = LoggerFactory.getLogger(FetchConfigurationsTask.class);
private final ConfigurationStore configurationStore;
private final Runnable runnable;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

By passing in a runable we can pass in a lambda which is nice for, among other things, having this leverage a protected BaseEppoClient method.

@aarsilv aarsilv requested a review from felipecsl August 14, 2024 04:17
@aarsilv aarsilv marked this pull request as ready for review August 14, 2024 04:17

@BeforeAll
public static void initMockServer() {
mockServer = new WireMockServer(TEST_PORT);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Unlike the shared common repository, these test cases use a mock local server, which makes them much faster. 🐎

@@ -1,34 +1,33 @@
package com.eppo.sdk;

import static cloud.eppo.helpers.AssignmentTestCase.parseTestCaseFile;
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is another file where I'd ignore the diff and just look at the new (green) code

Stream.of("option1", "option2", "option3").collect(Collectors.toSet());
new EppoClient.Builder()
.apiKey(DUMMY_FLAG_API_KEY)
.pollingIntervalMs(20)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

With Java, it was much easier to just use very small timeouts than to mock time out (or mock the Timer) like we do in JavaScript

Copy link
Contributor

@felipecsl felipecsl left a comment

Choose a reason for hiding this comment

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

awesome πŸ”₯

@@ -34,11 +34,12 @@ dependencies {
// Logback classic 1.3.x is compatible with java 8
implementation 'ch.qos.logback:logback-classic:1.3.14'

testImplementation 'org.projectlombok:lombok:1.18.24'
testImplementation 'cloud.eppo:sdk-common-jvm:3.0.0-SNAPSHOT:tests'
Copy link
Contributor

Choose a reason for hiding this comment

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

interesting, didn't know about this syntax

build.gradle Outdated
@@ -25,7 +25,7 @@ repositories {
}

dependencies {
implementation 'cloud.eppo:sdk-common-jvm:2.0.0-SNAPSHOT'
implementation 'cloud.eppo:sdk-common-jvm:3.0.0-SNAPSHOT'
Copy link
Contributor

Choose a reason for hiding this comment

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

we need to remember to publish sdk-common-jvm v3.0.0 and bump it here to the release version before releasing this lib

Copy link
Collaborator

@typotter typotter left a comment

Choose a reason for hiding this comment

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

Looks great. Glad you brought your πŸͺ“

@@ -6,7 +6,7 @@ plugins {
}

group = 'cloud.eppo'
version = '2.5.0-SNAPSHOT'
version = '3.0.0-SNAPSHOT'
Copy link
Collaborator

Choose a reason for hiding this comment

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

πŸŽ‰

@@ -7,38 +7,31 @@

public class FetchConfigurationsTask extends TimerTask {
Copy link
Collaborator

Choose a reason for hiding this comment

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

public class JitteryTimerTask?

@typotter typotter assigned aarsilv and unassigned typotter Aug 14, 2024
@aarsilv aarsilv merged commit be8eded into main Aug 16, 2024
3 checks passed
@aarsilv aarsilv deleted the aaron/ff-2842/use-updated-client branch August 16, 2024 02:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants