Skip to content

Conversation

@keelerm84
Copy link
Member

@keelerm84 keelerm84 commented Nov 19, 2025

Note

Introduces an experimental FDv2 data system (streaming/polling) with persistent-store support and FDv1 fallback, updates LDClient to use it when configured, adds v2 file/test data sources, and adjusts tests/CI/deps.

  • Data System (FDv2):
    • New core ldclient.impl.datasystem.fdv2 with orchestrated initializers/synchronizers, status providers, data availability, and persistent-store integration (read-only/read-write) with outage recovery and commit.
    • FDv1 remains default; LDClient now selects FDv2 when Config.datasystem_config is provided and evaluates via ReadOnlyStore; readiness uses DataAvailability.
    • New config/builders in ldclient/datasystem.py and ldclient/config.py (DataSystemConfig, builders for default/streaming/polling/custom, FDv1 fallback).
  • FDv2 Data Sources:
    • Streaming synchronizer ldclient.impl.datasourcev2.streaming (SSE, selector/basis support, diagnostics, env-id and fallback headers).
    • Polling initializer/synchronizer ldclient.impl.datasourcev2.polling (FDv2/FDv1 payload parsing, ETag/304, env-id/fallback handling).
    • Internal store ldclient.impl.datasystem.store (in-memory + optional persistence, change tracking, dependency propagation).
  • Integrations:
    • New v2 file data source Files.new_data_source_v2 and test data source integrations.test_datav2 implementing Initializer/Synchronizer.
    • Contract tests contract-tests/client_entity.py extended to configure data system (initializers/synchronizers, fallback, payload filter).
  • Interfaces/Protocol Types:
    • Expanded ldclient.interfaces: Initializer/Synchronizer, Selector, ChangeSet/Change, Basis, Update, DataStoreMode, ReadOnlyStore, and moved protocol event types.
  • Client:
    • ldclient/client.py: wiring to DataSystem, store access via _data_system.store, readiness via data_availability, diagnostics pass-through.
  • Tooling/CI/Deps:
    • CI: skip flaky tests via LD_SKIP_FLAKY_TESTS; Makefile creates .mypy_cache.
    • Deps: bump launchdarkly-eventsource to >=1.5.0, update pytest to ^8.0.0.
  • Tests:
    • Extensive new tests for FDv2 streaming/polling, persistence behavior, file/test data sources, and config builders.

Written by Cursor Bugbot for commit 23dae3d. This will update automatically on new commits. Configure here.

<!-- CURSOR_SUMMARY -->
> [!NOTE]
> Introduces FDv2 data system configuration and robust synchronizer
lifecycle (start/stop), integrates SSE streaming with payload filter,
implements an in-memory feature store, and updates tests and contract
client accordingly.
> 
> - **FDv2/Data System**:
> - Add `Synchronizer.stop()` to interface and implement stop/lifecycle
management in `StreamingDataSource` and `PollingDataSource`.
> - Enhance `FDv2` to track/stop the active synchronizer safely with
locks; ensure threads shut down cleanly.
> - Add `datasystem.config` builders (`polling_ds_builder`,
`streaming_ds_builder`), expose `fdv1_fallback_synchronizer` in config.
> - **Streaming**:
> - Switch to `ld_eventsource.SSEClient`; include payload filter in
stream URI.
> - Handle stream errors by interrupting/closing SSE; stop on
unrecoverable errors; ensure closure on exit.
> - **Polling**:
>   - Add stoppable sync loop with `_stop` flag and `stop()` method.
> - **Store**:
> - Implement thread-safe `InMemoryFeatureStore` with basic CRUD, init,
and diagnostics; integrate with `Store`.
> - **Contract tests**:
> - Support FDv2 `dataSystem` config (initializers/synchronizers,
payloadFilter) in `client_entity.py`.
> - **Tests**:
> - Update streaming synchronizer tests for new SSE client usage and
stop/interrupt behavior.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
e87daa0. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
In the previous setup, we would only check the fallback or recovery
conditions once the synchronizer returned an update. If the synchronizer
was stuck, or nothing was changing in the environment, we would never
check the conditions.

This configuration also exposed an interesting behavior. If the
synchronizer cannot connect, it will emit error updates. Each time we
receive an error, we check if we have failed to initialize for the last
10 seconds. If so, we re-create the primary synchronizer.

When it continues to fail, the first update will trigger the condition
check. And since it has still failed for 10 seconds, it will immediately
error out. With this change, we can be assured a synchronizer is given
at least 10 seconds to try before the condition is evaluated.
@keelerm84 keelerm84 requested a review from a team as a code owner November 19, 2025 22:02
@keelerm84 keelerm84 changed the title chore: Merge fdv2 feature branch into mainline feat(experimental): Release EAP support for FDv2 data system Nov 19, 2025
@keelerm84 keelerm84 merged commit aad6457 into main Nov 19, 2025
36 of 37 checks passed
@keelerm84 keelerm84 deleted the feat/fdv2 branch November 19, 2025 22:17
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.

3 participants