Skip to content
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

fix: getprecomputedinstance should always return an instance #151

Conversation

sameerank
Copy link
Contributor

@sameerank sameerank commented Jan 16, 2025


labels: mergeable

Fixes: #issue

Motivation and Context

Some feedback in a previous PR that we should avoid overwriting the Eppo client instance.

We shall prefer creating a new instance of the client in initialization instead of resetting the existing one.

This is challenging because it breaks the expected behavior that getPrecomputedInstance always returns an instance of EppoPrecomputedClient.

js-client-sdk/src/index.ts

Lines 784 to 786 in f5d4eb4

export function getPrecomputedInstance(): EppoPrecomputedClient {
return EppoPrecomputedJSClient.instance;
}

It would be undefined before any of the initialization functions (precomputedInit or offlinePrecomputedInit) are called. This is likely to happen in complex applications with race conditions between various rendering components. This means the code would need an extra protection that the singleton client is defined before calling client.getStringAssignment(..., defaultValue), and this is poor DX because they can't simply rely on the function falling back on returning the defaultValue if called before initialization and need to write in their own extra protection.

Description

This initializes the client with an instance with an empty precomputed config store.

So instead of doing

const eppoPrecomputedClient = getPrecomputedInstance();
const precomputedAssignment = eppoPrecomputedClient ? eppoPrecomputedClient.getStringAssignment(flagKey, defaultValue) : defaultValue;

you can just do

const eppoPrecomputedClient = getPrecomputedInstance();
const precomputedAssignment = eppoPrecomputedClient.getStringAssignment(flagKey, defaultValue);

How has this been tested?

@sameerank sameerank marked this pull request as draft January 16, 2025 19:56
@sameerank sameerank changed the title Sameeran/ff 3821 getprecomputedinstance should always return an instance fix: getprecomputedinstance should always return an instance Jan 16, 2025
@@ -608,7 +614,7 @@ export class EppoPrecomputedJSClient extends EppoPrecomputedClient {
export async function precomputedInit(
config: IPrecomputedClientConfig,
): Promise<EppoPrecomputedClient> {
if (EppoPrecomputedJSClient.instance) {
if (EppoPrecomputedJSClient.initialized) {
Copy link
Contributor Author

@sameerank sameerank Jan 16, 2025

Choose a reason for hiding this comment

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

Another bit of feedback was about "shutting down" the client #117 (comment)

Since the client instance now will always be defined, I am switching to use the initialized check. This makes it so you can't replace the singleton by re-running precomputedInit: it'll just return the previously initialized instance. There is a private method visible below (shutdownEppoPrecomputedClient ) that would need to be called first before re-initializing, if we want to use it here to allow re-initialization/overwriting the singleton

@sameerank sameerank marked this pull request as ready for review January 16, 2025 20:21
@@ -557,7 +557,13 @@ export function getConfigUrl(apiKey: string, baseUrl?: string): URL {
* @public
*/
export class EppoPrecomputedJSClient extends EppoPrecomputedClient {
public static instance: EppoPrecomputedJSClient;
public static instance = new EppoPrecomputedJSClient({
Copy link
Collaborator

Choose a reason for hiding this comment

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

just to confirm, this instantiation doesn't kick off any network requests or polling, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope, you have to go through the precomputedInit method to start the poller

@sameerank sameerank merged commit ec71cac into main Jan 17, 2025
8 checks passed
@sameerank sameerank deleted the sameeran/ff-3821-getprecomputedinstance-should-always-return-an-instance branch January 17, 2025 18:17
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.

2 participants