Skip to content

Conversation

@typotter
Copy link
Collaborator

@typotter typotter commented Jan 7, 2026

Eppo Internal:
🎟️ Fixes FFL-1683

Motivation and Context

Previously, when registering a configuration change callback via the Builder's onConfigurationChange() method, there was no way to unsubscribe from these notifications. The callback would continue to fire for every configuration change (initialization, manual loadConfiguration() calls, and polling updates) for the lifetime of the EppoClient instance.

This is problematic for initialization scenarios where developers only want to be notified once when the initial configuration is loaded, not on subsequent updates. Without an unsubscribe mechanism, developers would receive unwanted callbacks during polling or manual reloads.

While BaseEppoClient.onConfigurationChange() already returns an unsubscribe Runnable, the Android SDK wrapper wasn't capturing or exposing this functionality, making it impossible to unsubscribe from the Builder-registered callback.

Because we are building the Android client with a Builder, we don't have a clean vector to return the unsubscribe runnable without breaking the Builder convention or introducing a breaking change to the API. In addition to this change, we can add an unsubscribe(listener) to the BaseEppoClient to allow unsubscribing.

Description

This PR adds an optional oneShot boolean parameter to the Builder's onConfigurationChange() method. When oneShot=true, the callback automatically unsubscribes itself after the first invocation, making it perfect for initialization scenarios.

Implementation Details

OneShotConfigCallback Wrapper Class (EppoClient.java:160-185):
Builder Method Overload (EppoClient.java:291-302):
Initialization Logic (EppoClient.java:354-360):

How has this been documented?

Code Documentation
TODO: Customer Comms

How has this been tested?

New Tesst

    Add ability to auto-unsubscribe from configuration changes after first
    invocation by adding an optional oneShot boolean parameter to the
    Builder's onConfigurationChange() method.

    When oneShot=true, the callback is automatically unsubscribed after
    the first configuration change, which is useful for initialization
    scenarios where you only want to be notified once.

    The implementation uses an OneShotConfigCallback wrapper class that
    delegates to the user's callback and then executes the unsubscribe
    Runnable returned by BaseEppoClient.onConfigurationChange(). The
    wrapping happens immediately in the Builder method, keeping the logic
    clean and avoiding the need to store state about oneShot mode.

    Fixes FFL-1683
@typotter typotter requested a review from aarsilv January 7, 2026 16:16
Copy link
Contributor

@aarsilv aarsilv left a comment

Choose a reason for hiding this comment

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

Makes sense as a starting point to have the config change be one-time, auto-unsubscribed

Copy link

@dd-oleksii dd-oleksii left a comment

Choose a reason for hiding this comment

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

Shall we just add an unsubscribe to BaseEppoClient, so we don't need one-shot special handling?

delegate.accept(config);
} finally {
if (unsubscriber != null) {
unsubscriber.run();

Choose a reason for hiding this comment

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

minor: shall we unsubscribe before running accept on delegate? (could matter in edge cases when accept() is running for too long and we receive another configuration?)

Copy link
Contributor

Choose a reason for hiding this comment

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

I was actually thinking the same thing!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

good catch here. The base callbackmanager doesn't have any locking 🫠

@typotter
Copy link
Collaborator Author

typotter commented Jan 7, 2026

Shall we just add an unsubscribe to BaseEppoClient, so we don't need one-shot special handling?

fair Eppo-exp/sdk-common-jdk#185

@typotter typotter requested a review from dd-oleksii January 7, 2026 18:20
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.

4 participants