Skip to content

feat: Add FDv2 polling sources to the client - #610

Merged
beekld merged 7 commits into
mainfrom
bklimt/SDK-3030/client-fdv2-polling
Sep 24, 2026
Merged

beekld merged 7 commits into
mainfrom
bklimt/SDK-3030/client-fdv2-polling

Conversation

@beekld

@beekld beekld commented Sep 10, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds the FDv2 polling sources -- a one-shot polling initializer and an interval-based polling synchronizer -- over a shared request builder and response handler that feed the response through the protocol handler and the changeset translation.

  • The evaluation context travels base64url-encoded in the request path (default) or in a POST body. The FDv1 REPORT option is not carried forward.
  • The synchronizer sends the selector's state as the basis query parameter for deltas, with a poll-interval floor to avoid hammering the service.
  • The environment id and any FDv1 fallback directive are read from the response headers. A directive carried on a goodbye message takes precedence.

Design note: this client sends no conditional-request validator (If-None-Match/ETag), unlike the Flutter and Android clients, which track a per-context ETag and act on real 304 responses. The spec lists omitting If-None-Match entirely as an accepted way to avoid the cross-context ETag hazard, and since every SDK already sends the basis selector for deltas, dropping the ETag costs little here. Because no If-None-Match is ever sent, a 304 should not occur, so the 304 -> none handling is defensive.

Internal only. The orchestrator that runs these arrives in a later change.


Note

Overview
Adds FDv2 HTTP polling to the C++ client SDK: shared plumbing to build /sdk/poll/eval requests and turn poll responses into FDv2SourceResult via the existing protocol handler and changeset translation.

FDv2PollingInitializer performs a one-shot basis load; FDv2PollingSynchronizer polls on an interval (clamped to the SDK minimum), sends selector state as basis, and supports cancel/shutdown via Close(). Context can travel as base64url in the GET path or JSON in a POST body (FDv2RequestConfig). The client does not send If-None-Match; 304 is still mapped defensively to a none changeset. Response headers supply environment id and optional FDv1 fallback (body goodbye TTL wins over header).

AsioRequester is refactored so redirect/async paths capture the SSL context explicitly instead of this, avoiding lifetime issues in nested callbacks.

Unit tests cover request shaping, response/error/fallback behavior, and synchronizer timing/close semantics. Wiring into the public data-source orchestrator is left for a follow-up.

Reviewed by Cursor Bugbot for commit bc9ead6. Bugbot is set up for automated code reviews on this repo. Configure here.

@beekld
beekld added this pull request to stack #608 September 10, 2026 23:19
@beekld
beekld force-pushed the bklimt/SDK-3030/client-fdv2-polling branch from 6485e51 to d536b60 Compare September 11, 2026 01:39
@beekld
beekld marked this pull request as ready for review September 11, 2026 21:23
@beekld
beekld requested a review from a team as a code owner September 11, 2026 21:23

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread libs/client-sdk/src/data_sources/fdv2/polling_synchronizer.cpp
@beekld
beekld force-pushed the bklimt/SDK-3030/client-fdv2-polling branch from 6960b1e to 8c8d6c2 Compare September 16, 2026 20:56

@cursor cursor Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread libs/client-sdk/src/data_sources/fdv2/polling_initializer.hpp
@beekld
beekld force-pushed the bklimt/SDK-3030/client-fdv2-polling branch from 8c8d6c2 to 61fd504 Compare September 16, 2026 21:25

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 61fd504. Configure here.

Comment thread libs/client-sdk/src/data_sources/fdv2/polling_initializer.cpp
Base automatically changed from bklimt/SDK-3029/client-fdv2-source-interfaces to main September 18, 2026 16:57
@beekld
beekld force-pushed the bklimt/SDK-3030/client-fdv2-polling branch from 4f1769f to 8580a33 Compare September 18, 2026 16:57
@beekld
beekld force-pushed the bklimt/SDK-3030/client-fdv2-polling branch from 8580a33 to bc9ead6 Compare September 24, 2026 21:22
@beekld
beekld merged commit 9a2f9a3 into main Sep 24, 2026
53 checks passed
@beekld
beekld deleted the bklimt/SDK-3030/client-fdv2-polling branch September 24, 2026 21:26
@github-actions github-actions Bot mentioned this pull request Sep 24, 2026
jsonbailey pushed a commit that referenced this pull request Sep 28, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>launchdarkly-cpp-client: 3.12.0</summary>

##
[3.12.0](launchdarkly-cpp-client-v3.11.4...launchdarkly-cpp-client-v3.12.0)
(2026-09-24)


### Features

* Add FDv2 initializer and synchronizer interfaces to the client
([#609](#609))
([d6c7fe2](d6c7fe2))
* Add FDv2 polling sources to the client
([#610](#610))
([9a2f9a3](9a2f9a3))
* Add the FDv2 streaming synchronizer to the client SDK
([#611](#611))
([edf0e4f](edf0e4f))
* Apply FDv2 changesets to the client flag store transactionally
([#607](#607))
([5fb0c75](5fb0c75))
* Translate FDv2 changesets into client flag changes
([#606](#606))
([61a248f](61a248f))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/cpp-internal bumped from 0.14.2 to 0.15.0
    * @launchdarkly/cpp-sse-client bumped from 0.7.1 to 0.8.0
</details>

<details><summary>launchdarkly-cpp-internal: 0.15.0</summary>

##
[0.15.0](launchdarkly-cpp-internal-v0.14.2...launchdarkly-cpp-internal-v0.15.0)
(2026-09-24)


### Features

* Add FDv2 polling sources to the client
([#610](#610))
([9a2f9a3](9a2f9a3))
* Translate FDv2 changesets into client flag changes
([#606](#606))
([61a248f](61a248f))


### Bug Fixes

* Parse the event Date header in the classic locale
([#604](#604))
([8c0d6a8](8c0d6a8))
</details>

<details><summary>launchdarkly-cpp-server: 3.14.0</summary>

##
[3.14.0](launchdarkly-cpp-server-v3.13.1...launchdarkly-cpp-server-v3.14.0)
(2026-09-24)


### Features

* Add the FDv2 streaming synchronizer to the client SDK
([#611](#611))
([edf0e4f](edf0e4f))


### Bug Fixes

* allow lazy load evaluations when $inited key is not set
([#508](#508))
([120b79a](120b79a))
* Read keyed tombstones as deleted, not as live items
([#615](#615))
([c2d54e1](c2d54e1))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/cpp-internal bumped from 0.14.2 to 0.15.0
    * @launchdarkly/cpp-sse-client bumped from 0.7.1 to 0.8.0
</details>

<details><summary>launchdarkly-cpp-server-dynamodb-source:
0.3.2</summary>

##
[0.3.2](launchdarkly-cpp-server-dynamodb-source-v0.3.1...launchdarkly-cpp-server-dynamodb-source-v0.3.2)
(2026-09-24)


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/cpp-server bumped from 3.13.1 to 3.14.0
</details>

<details><summary>launchdarkly-cpp-server-otel: 0.1.6</summary>

##
[0.1.6](launchdarkly-cpp-server-otel-v0.1.5...launchdarkly-cpp-server-otel-v0.1.6)
(2026-09-24)


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/cpp-server bumped from 3.13.1 to 3.14.0
</details>

<details><summary>launchdarkly-cpp-server-redis-source: 2.4.2</summary>

##
[2.4.2](launchdarkly-cpp-server-redis-source-v2.4.1...launchdarkly-cpp-server-redis-source-v2.4.2)
(2026-09-24)


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/cpp-server bumped from 3.13.1 to 3.14.0
</details>

<details><summary>launchdarkly-cpp-sse-client: 0.8.0</summary>

##
[0.8.0](launchdarkly-cpp-sse-client-v0.7.1...launchdarkly-cpp-sse-client-v0.8.0)
(2026-09-24)


### Features

* Add the FDv2 streaming synchronizer to the client SDK
([#611](#611))
([edf0e4f](edf0e4f))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> This is a **Release Please** cut that bumps semver across the monorepo
and aligns version strings in CMake, `package.json`, public `Version()`
APIs, and tests—without changing SDK logic in this diff.
> 
> **Client SDK 3.12.0** (with **cpp-internal 0.15.0** and **sse-client
0.8.0**) is documented as shipping **FDv2** on the client:
initializer/synchronizer interfaces, polling and streaming sources,
changeset translation, and transactional application to the flag store.
> 
> **Server SDK 3.14.0** picks up the same dependency bumps plus
changelog notes for lazy-load evaluation when `$inited` is missing and
treating keyed tombstones as deletions. **Redis**, **DynamoDB**, and
**OTel** integration packages are re-released only to depend on server
**3.14.0**.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
c47c227. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

2 participants