Skip to content

fix: Fall back from a silent FDv2 synchronizer before data has been received - #237

Draft
kinyoklion wants to merge 1 commit into
mainfrom
devin/1792084582-fdv2-startup-fallback
Draft

kinyoklion wants to merge 1 commit into
mainfrom
devin/1792084582-fdv2-startup-fallback

Conversation

@kinyoklion

@kinyoklion kinyoklion commented Oct 15, 2026 •

Copy link
Copy Markdown
Member

When the SDK has no data yet, it now falls back from an FDv2 synchronizer that sends nothing after 10s, rather than waiting for the 5-minute stream read timeout. This ports launchdarkly/go-server-sdk#461.

  • Before any data is applied, FallbackCondition starts a 10s timer right away, and a change set cancels it. After data is applied, the existing behavior applies unchanged: wait for INTERRUPTED, then wait the 2-minute fallback.
  • dataApplied is set from the return value of DataSourceUpdateSinkV2.apply, so a change set the store rejects doesn't count.
  • Removes all entries from contract-tests/test-suppressions-fdv2.txt. The file stays because CI references it.
  • sdk-test-harness v3.2.0-alpha.13, run with long-running tests and nothing suppressed: all tests passed (4890 ran). Before this change, recoverable fallback with recovery and permanent fallback with recovery failed.

Companion CI PR: #236

Implementation details

Requirements

  • I have added test coverage for new or changed functionality
  • I have followed the repository's pull request submission guidelines
  • I have validated my changes against all supported platform versions

Related issues

launchdarkly/go-server-sdk#461 (same fix in Go).

Describe the solution you've provided

Root cause: FallbackCondition only started its timer on an INTERRUPTED status. A synchronizer that accepts the connection but sends nothing reports no status until the read timeout (5 minutes). With two silent synchronizers at the front of the list, initialization ran past the harness's 60s start wait.

  • FDv2DataSource tracks dataApplied. It has a new constructor overload that takes initializationFallbackTimeout, used only by tests. The default is 10s.
  • FallbackCondition.Factory takes the initialization timeout and a BooleanSupplier. Until data has been applied, build() returns a condition whose timer is already running. The old two-argument factory constructor behaves as before.

Tests:

  • FDv2DataSourceFallbackConditionTest: the initialization timer fires without a status; a change set cancels it; the factory uses it only before data has been applied.
  • FDv2DataSourceTest: a silent synchronizer during startup falls back to the next one; a silent synchronizer after data has been applied does not fall back quickly.
  • ./gradlew test --tests '*FDv2*' passes.

Describe alternatives you've considered

Shortening the stream read timeout. Rejected because it would also affect healthy steady-state connections.

Additional context

No public API changes.

Link to Devin session: https://app.devin.ai/sessions/27eec66fcd28426ca483cf5a81b85704
Open in Devin Desktop: https://app.devin.ai/desktop/session/27eec66fcd28426ca483cf5a81b85704?variant=devin
Requested by: @kinyoklion

SDK-3335

…eceived

Co-Authored-By: rlamb@launchdarkly.com <4955475+kinyoklion@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

This branch has not been deployed

No deployments
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