chore: adds DataSystem and ConnectionMode customization APIs#338
Merged
tanderson-ld merged 29 commits intomainfrom Apr 1, 2026
Merged
chore: adds DataSystem and ConnectionMode customization APIs#338tanderson-ld merged 29 commits intomainfrom
tanderson-ld merged 29 commits intomainfrom
Conversation
Introduces the core types for FDv2 mode resolution (CONNMODE spec): - ConnectionMode: enum for streaming, polling, offline, one-shot, background - ModeDefinition: initializer/synchronizer lists per mode with stubbed configurers - ModeState: platform state snapshot (foreground, networkAvailable) - ModeResolutionEntry: condition + mode pair for resolution table entries - ModeResolutionTable: ordered first-match-wins resolver with MOBILE default table - ModeAware: interface for DataSources that support runtime switchMode() All types are package-private. No changes to existing code.
Add ResolvedModeDefinition and mode-table constructors so FDv2DataSource can look up initializer/synchronizer factories per ConnectionMode. switchMode() tears down the current SourceManager, builds a new one with the target mode's synchronizers (skipping initializers per CONNMODE 2.0.1), and schedules execution on the background executor. runSynchronizers() now takes an explicit SourceManager parameter to prevent a race where the finally block could close a SourceManager swapped in by a concurrent switchMode().
Introduces FDv2DataSourceBuilder, a ComponentConfigurer<DataSource> that resolves the ModeDefinition table's ComponentConfigurers into DataSourceFactories at build time by capturing the ClientContext. The configurers are currently stubbed (return null); real wiring of concrete initializer/synchronizer types will follow in a subsequent commit.
…ourceBuilder Replace stub configurers with concrete factories that create FDv2PollingInitializer, FDv2PollingSynchronizer, and FDv2StreamingSynchronizer. Shared dependencies (SelectorSource, ScheduledExecutorService) are created once per build() call; each factory creates a fresh DefaultFDv2Requestor for lifecycle isolation. Add FDv2 endpoint path constants to StandardEndpoints. Thread TransactionalDataStore through ClientContextImpl and ConnectivityManager so the builder can construct SelectorSourceFacade from ClientContext.
ConnectivityManager now detects ModeAware data sources and routes foreground, connectivity, and force-offline state changes through resolveAndSwitchMode() instead of the legacy teardown/rebuild cycle.
…d switching Replace Approach 1 implementation with Approach 2, which the team preferred for its cleaner architecture: - ConnectivityManager owns the resolved mode table and performs ModeState -> ConnectionMode -> ResolvedModeDefinition lookup - FDv2DataSource receives ResolvedModeDefinition via switchMode() and has no internal mode table - FDv2DataSourceBuilder uses a unified ComponentConfigurer-based code path for both production and test mode tables - ResolvedModeDefinition is a top-level class rather than an inner class of FDv2DataSource - ConnectionMode is a final class with static instances instead of a Java enum Made-with: Cursor
FDv2DataSource now explicitly implements both DataSource and ModeAware, keeping the two interfaces independent. Made-with: Cursor
…n ConnectivityManager Extract updateEventProcessor() and handleModeStateChange() so that event processor state (setOffline, setInBackground) is managed independently from data source lifecycle. Both platform listeners and setForceOffline() now route through handleModeStateChange(), which snapshots state once and updates each subsystem separately. Made-with: Cursor
…o prevent race condition SourceManager now owns a switchSynchronizers() method that atomically swaps the synchronizer list under the existing lock, eliminating the window where two runSynchronizers() loops could push data into the update sink concurrently. FDv2DataSource keeps a single final SourceManager and uses an AtomicBoolean guard to ensure only one execution loop runs at a time. Made-with: Cursor
…pdateDataSource handleModeStateChange() now simply updates the event processor and delegates to updateDataSource(). The FDv2 ModeAware early-return and FDv1 needsRefresh() check both live inside updateDataSource, keeping the branching logic in one place. Made-with: Cursor
…nectivityManager level Per updated CSFDV2 spec and JS implementation, mode switching now tears down the old data source and builds a new one rather than swapping internal synchronizers. Delete ModeAware interface, remove switchMode() from FDv2DataSource and switchSynchronizers() from SourceManager. FDv2DataSourceBuilder becomes the sole owner of mode resolution via setActiveMode()/build(), with ConnectivityManager using a useFDv2ModeResolution flag to route FDv2 through the new path while preserving FDv1 behavior. Implements CSFDV2 5.3.8 (retain data source when old and new modes share the same ModeDefinition). Made-with: Cursor
- Short-circuit forceOffline in resolveMode() so ModeState reflects actual platform state - Match ConnectionMode string values to cross-SDK spec (lowercase, hyphenated) - Add Javadoc to ConnectionMode, ClientContextImpl overloads, and FDv2DataSource internals - Inline FDv2DataSourceBuilder casts in ConnectivityManager - Restore try/finally and explanatory comments in runSynchronizers Made-with: Cursor
- Extract DataSourceSetup helper and makePollingRequestor() to eliminate duplicated configurer boilerplate in FDv2DataSourceBuilder - Share builder's sharedExecutor across all components to prevent thread pool leaks on mode switches; increase pool size from 2 to 4 - Make FDv2DataSourceBuilder implement Closeable; shut down executor in ConnectivityManager.shutDown() - Honor backgroundUpdatingDisabled in FDv2 mode resolution by adding the flag to ModeState and ModeResolutionTable Made-with: Cursor
- ConnectivityManager: use .equals() for ModeDefinition comparison, synchronize handleModeStateChange() - FDv2DataSourceBuilder: remove redundant unmodifiableMap() wrapping - ModeResolutionTable: use explicit default mode instead of catch-all entry - Add 5 FDv1 round-trip tests for offline, network, and foreground transitions
Move resolveMode() into updateDataSource so it covers both startup and state-change paths, eliminating the duplicate call in startUp that was always overwritten. Made-with: Cursor
tanderson-ld
commented
Mar 26, 2026
...-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/PollingSynchronizerBuilder.java
Outdated
Show resolved
Hide resolved
kinyoklion
reviewed
Mar 26, 2026
...lient-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/ConnectionModeBuilder.java
Outdated
Show resolved
Hide resolved
...rkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/DataSystemComponents.java
Show resolved
Hide resolved
...rkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/DataSystemComponents.java
Show resolved
Hide resolved
kinyoklion
reviewed
Mar 26, 2026
...id-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/DataSystemBuilder.java
Show resolved
Hide resolved
Contributor
Author
|
Need to add e2e integration tests. |
kinyoklion
approved these changes
Mar 27, 2026
Base automatically changed from
aaronz/SDK-1956/mode-resolution-and-switching
to
main
March 27, 2026 21:33
...arkly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/ConnectivityManager.java
Show resolved
Hide resolved
...kly-android-client-sdk/src/main/java/com/launchdarkly/sdk/android/FDv2DataSourceBuilder.java
Show resolved
Hide resolved
...id-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/DataSystemBuilder.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
...id-client-sdk/src/main/java/com/launchdarkly/sdk/android/integrations/DataSystemBuilder.java
Show resolved
Hide resolved
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Requirements
I have added test coverage for new or changed functionality
STILL NEED TO ADD e2e androidTest instrumented tests for transitions
I have followed the repository's pull request submission guidelines
I have validated my changes against all supported platform versions
Related issues
SDK-1837, SDK-1821
Describe the solution you've provided
Adds DataSystem API with DataSystem builder and connection mode customization APIs. Integrates this configuration into the ConnectivityManager and makes adjustments to FDv2DataSourceBuilder and related initializer / synchronizer components to support existing top level APIs for controlling datasource behavior (e.g. offline, disableBackgroundUpdates, etc...)
Note
High Risk
Touches core initialization/mode-switching and flag update application semantics (FDv2), which can affect connectivity behavior and when/which flag updates are applied across foreground/background/offline transitions.
Overview
Adds an early-access FDv2 Data System configuration surface:
LDConfig.Builder#dataSystem(Components.dataSystem())withDataSystemBuilder, customizable per-ConnectionModepipelines (ConnectionModeBuilder+DataSystemComponents), and granular automatic mode switching control (AutomaticModeSwitchingConfig).Wires the new configuration into runtime behavior by updating
ConnectivityManagerto use a per-configModeResolutionTable, respect lifecycle/network auto-switch toggles, and provide temporary FDv2-to-publicConnectionInformationstatus mapping; updatesFDv2DataSourceBuilderto build mode pipelines from newDataSourceBuildInputs/DataSourceBuildercontracts.Adjusts FDv2 partial update semantics by applying partial changes without version gating in
ContextDataManager, fixes FDv2 start failure to consistently surface errors, and adds new Android instrumented + JVM tests covering polling/streaming, partial updates/listeners, lifecycle/network transitions, and custom mode resolution.Written by Cursor Bugbot for commit a85839f. This will update automatically on new commits. Configure here.