-
Notifications
You must be signed in to change notification settings - Fork 1
Remove singleton pattern #28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
withSourcesJar() | ||
} | ||
|
||
tasks.register('testJar', Jar) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also providing a testJar artifact so upstream SDKs can use our handy test utilities. Sharing is caring!
// Custom task to ensure we can conditionally publish either a release or snapshot artifact | ||
// based on a command line switch. See github workflow files for more details on usage. | ||
task checkVersion { | ||
tasks.register('checkVersion') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IntelliJ said tasks.register()
and later on configureEach
below is more 1337
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
h4x0r
private static final boolean DEFAULT_IS_GRACEFUL_MODE = true; | ||
|
||
protected static final String DEFAULT_HOST = "https://fscdn.eppo.cloud"; | ||
protected final ConfigurationRequestor requestor; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
protected so upstream SDKs can trigger a (re)load
if (apiKey == null) { | ||
throw new IllegalArgumentException("Unable to initialize Eppo SDK due to missing API key"); | ||
} | ||
if (sdkName == null || sdkVersion == null) { | ||
throw new IllegalArgumentException( | ||
"Unable to initialize Eppo SDK due to missing SDK name or version"); | ||
} | ||
if (host == null) { | ||
host = DEFAULT_HOST; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved validation to the constructor so each SDK's builder doesn't have to worry about it
|
||
EppoHttpClient httpClient = buildHttpClient(host, apiKey, sdkName, sdkVersion); | ||
this.configurationStore = configurationStore; | ||
this.configurationStore = new ConfigurationStore(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we were always just passing in new ConfigurationStore()
so in-lining this for now until we handle caching at which point I reckon this may find its way back to the constructor, but didn't want to put the cart before the horse.
private final ObjectMapper mapper = | ||
new ObjectMapper().registerModule(AssignmentTestCase.assignmentTestCaseModule()); | ||
|
||
private BaseEppoClient eppoClient; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not static because for these tests we often initialize a new client, so we use the two methods below to get a new client for each test as needed
|
||
private void initClient( | ||
String host, boolean isGracefulMode, boolean isConfigObfuscated, String apiKey) { | ||
private void initClient(boolean isGracefulMode, boolean isConfigObfuscated) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to pass in host and API key as they are always the same
verify(mockAssignmentLogger, times(1)).logAssignment(assignmentLogCaptor.capture()); | ||
} | ||
|
||
private void mockHttpResponse(String responseBody) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved to a newly-created TestUtils
class so it can be used upstream
|
||
public void setFileName(String fileName) { | ||
this.fileName = fileName; | ||
private static final ObjectMapper mapper = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Below is where I relocated all the useful AssignmentTestCase
related utility methods. They are public so they can be used by upstream SDks
|
||
public void setFileName(String fileName) { | ||
this.fileName = fileName; | ||
public static Stream<Arguments> getBanditTestData() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here is why I relocated all the BanditTestCase
-related utility methods, also public.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great. appreciate all the comments to navigate the changes!
private static EppoHttpClient httpClientOverride = null; | ||
|
||
private BaseEppoClient( | ||
public BaseEppoClient( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be protected so it's only callable by subclasses?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea! I had it public as it's used by automated tests, but forgot it will still have package access. Will change!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to making this protected
this.sdkVersion = sdkVersion; | ||
// For now, the configuration is only obfuscated for Android clients | ||
this.isConfigObfuscated = sdkName.toLowerCase().contains("android"); | ||
this.isConfigObfuscated = expectObfuscatedConfig; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π
default: | ||
log.debug("Fetch failed with status code: " + response.code()); | ||
callback.onFailure("Bad response from URL " + httpUrl); | ||
if (response.code() == HttpURLConnection.HTTP_FORBIDDEN) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
π
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
private static EppoHttpClient httpClientOverride = null; | ||
|
||
private BaseEppoClient( | ||
public BaseEppoClient( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 to making this protected
import java.lang.reflect.Field; | ||
import okhttp3.*; | ||
|
||
public class TestUtils { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super minor nit: good practice to make "utils"-like classes final
to tell users they're not supposed to subclass it
.get(anyString(), any(EppoHttpClientRequestCallback.class)); | ||
|
||
setBaseClientHttpClientOverrideField(mockHttpClient); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd honestly prefer if we used OkHttp's excellent MockWebServer
(https://github.com/square/okhttp/tree/master/mockwebserver) but this is low priority
* Eppo Client with shared UFC tests passing (#23) * tests passing for rule evaluator, flag evaluator, and eppo value * work in progress * shared UFC tests passing * don't check in test data * changes from self-review of PR * apply spotless linter * working on tests * better test logging * use make test for tests * Add bandit support (#25) * bandit test harness ready * add bandit result * set up for dropping in bandit evaluation * bandit deserialization wired up * loading bandit parameters * bandit stuff happening * shared bandit tests passing * bandit logger classes * bandit log test passing * more tests for logger * bandit tests for graceful mode * apply spotless formatting autofix * changes from self-review of PR so far * more changes from self-review of PR * more changes from self-review * make test less fragile * bump version; don't sign local maven * bandit logging errors should be non-fatal * use normalized probability floor * update result before even attempting to log bandit * spotless π * do the rename (#26) * Remove singleton pattern (#28) * work in progress * remove singleton for base client * linter * expose bandit test harnesses * expose test uilities * changes from self-review of PR * make base client constructor protected
Eppo Internal:
ποΈ Ticket: FF-3033 - Update common SDK repository for upstream use by Java SDK
π―ββοΈ Related PR:
java-server-sdk #70
This update makes this common shared SDK easier to integrate with upstream SDKs. It accomplishes this with a few key changes:
EppoHttpClient
's request callback a public interface,EppoHttpClientRequestCallback
I also implemented some additional random cleanup as recommended by the IntelliJ IDE Inspections