Skip to content

fix: enable SSE reconnect in multi-user client - #228

Open
vazarkevych wants to merge 2 commits into
mainfrom
fix/sse-reconnection
Open

fix: enable SSE reconnect in multi-user client#228
vazarkevych wants to merge 2 commits into
mainfrom
fix/sse-reconnection

Conversation

@vazarkevych

@vazarkevych vazarkevych commented Jul 23, 2026

Copy link
Copy Markdown
Collaborator

Problem

In multi-user mode, GrowthBookClient always called the no-arg
repository.initialize() (in initializeFeaturesRepository()), which delegates to
initialize(false). That hardwires retryOnFailure = false, so
scheduleSseReconnect(...) early-returns and the SSE reconnect machinery is unreachable.

As a result, a GrowthBookClient using FeatureRefreshStrategy.SERVER_SENT_EVENTS
permanently stops receiving feature updates after the first abnormal stream failure
(connection reset, proxy/pod restart, mid-stream IOException) — silently:

  • no reconnect attempt;
  • no polling fallback (schedulePolling() early-returns for SSE);
  • no observability — FeatureRefreshCallback.onError(...) never fires.

Both onFailure and onClose route through scheduleSseReconnect, so multi-user + SSE
also stops reconnecting on a graceful close. Options.retryPolicy (exponential
backoff) was configurable but never actually engaged.

Fix

Expose the flag on Options and thread it through the single choke point:

  • Options.sseReconnectOnFailure — new option, defaults to true, with
    isSseReconnectOnFailure() returning true unless explicitly disabled. Added as the
    last constructor parameter to preserve the existing positional constructor signature.
  • GrowthBookClient.initializeFeaturesRepository() now calls
    repository.initialize(options.isSseReconnectOnFailure()) instead of the no-arg form.

Reconnect is on by default (bounded by retryPolicy), and callers can opt out with
Options.builder().sseReconnectOnFailure(false). The single-user
GBFeaturesRepository.initialize() default (false) is unchanged to avoid a broader
public-API behavior change.

Tests

backoff) was configurable but never actually engaged.

Fix

Expose the flag on Options and thread it through the single choke point:

  • Options.sseReconnectOnFailure — new option, defaults to true, with
    isSseReconnectOnFailure() returning true unless explicitly disabled. Added as the
    last constructor parameter to preserve the existing positional constructor signature.
  • GrowthBookClient.initializeFeaturesRepository() now calls
    repository.initialize(options.isSseReconnectOnFailure()) instead of the no-arg form.

Reconnect is on by default (bounded by retryPolicy), and callers can opt out with
Options.builder().sseReconnectOnFailure(false). The single-user
GBFeaturesRepository.initialize() default (false) is unchanged to avoid a broader
public-API behavior change.

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.

1 participant