Skip to content

feat: Apply RETRY to FDv2 synchronizer orchestration - #423

Draft
beekld wants to merge 12 commits into
mainfrom
bklimt/SDK-3507/retry-orchestration
Draft

beekld wants to merge 12 commits into
mainfrom
bklimt/SDK-3507/retry-orchestration

Conversation

@beekld

@beekld beekld commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Applies the RETRY behavior to FDv2 synchronizer orchestration in the Android SDK, following launchdarkly/java-core#252 and launchdarkly/java-core#253. A synchronizer that fails is parked and retried later, instead of being blocked for good.

Parking

  • A synchronizer that fails unexpectedly is parked. That covers a terminal error, a failed or throwing next(), a failure to build, or shutting down on its own. The park delay starts at 5 minutes, doubles with each failure up to 1 hour, and has jitter. After a park, the next synchronizer starts after a failover delay of 0.5-1 seconds.
  • A synchronizer's park count resets when it meets its reset threshold. For the FDv2 polling and FDv1 fallback synchronizers, that's two successful polls in a row. For streaming, it's staying connected for 60 seconds.
  • When every synchronizer is parked, the data source reports INTERRUPTED and waits for the earliest unpark time. Synchronization stops only when the data source is stopped.
  • Fallback and recovery switch only to a synchronizer that isn't parked. When the fallback condition is met but no other synchronizer is available, the current synchronizer keeps running.
  • An exception on the stream thread is now terminal, so the streaming synchronizer is parked and rebuilt instead of staying dead.

Directed fallback

  • The fallback to FDv1 now ends after a TTL, which defaults to 1 hour with jitter. The data source then restarts the FDv2 synchronizers.
  • A directive received during the fallback extends the TTL.
  • A directive with no FDv1 fallback synchronizer configured is no longer ignored. The data source reports INTERRUPTED, runs no synchronizer, and restarts the FDv2 synchronizers when the TTL ends.
  • When an initializer's directive comes with a payload that has no selector, the payload is applied but no longer marks the data source ready. Readiness waits for the next source's data, as the data system spec requires.

Deadlines

  • The synchronizer loop checks its fallback, recovery, unpark, and TTL deadlines each time it wakes. The deadlines use System.nanoTime(), so changes to the system clock don't move them. FDv2DataSourceConditions is removed.

Public API

This extends the public FDv2SourceResult class in com.launchdarkly.sdk.android.subsystems, the result type that initializers and synchronizers return. It adds two methods:

  • isResetThresholdMet() returns true if the source met its reset threshold at the time of the result. When a synchronizer returns such a result, the data source resets that synchronizer's park count. Results from the existing changeSet() and status() factory methods return false.
  • withResetThresholdMet() returns a copy of the result with isResetThresholdMet() set to true.

FDv2SourceResult is part of the early access FDv2 data system. It now carries the same note as the other early access types, saying that it is not stable and not subject to backwards compatibility guarantees or semantic versioning.

Not included

  • Treating TLS certificate failures as terminal. That needs FailureClass from a newer java-sdk-internal.
  • Honoring Retry-After, and reading the TTL from the response. Every directive uses the 1-hour default.
  • The temporary FDv2 status sink in ConnectivityManager treats INTERRUPTED with no error as a successful connection. Some of the new INTERRUPTED reports have no error, as in Java. That will be fixed separately.

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