Skip to content

fix: Notify dependent flags when an FDv2 prerequisite or segment changes - #470

Merged
kinyoklion merged 3 commits into
mainfrom
rlamb/fdv2-store-dependency-keys
Oct 23, 2026
Merged

kinyoklion merged 3 commits into
mainfrom
rlamb/fdv2-store-dependency-keys

Conversation

@kinyoklion

@kinyoklion kinyoklion commented Oct 21, 2026 •

Copy link
Copy Markdown
Member

With the FDv2 data system, flag change listeners never hear about flags that depend on a changed prerequisite or segment. Only the changed item itself is reported. The FDv2 store passes change keys to the dependency tracker as symbols, but the tracker records dependents under the string keys that prerequisite and segment references use, so every lookup misses. Deltas and full data sets are both affected.

The store now converts keys to strings before it uses the tracker, as the FDv1 data source update sink already does. Collection keys stay symbols, so the full-data-set diff is unchanged.

New Store specs apply symbol-keyed changes (prerequisite chains, a segment, a full data set) and assert the exact set of notified flags.

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

SDK-3355


Note

Overview
Fixes FDv2 flag change notifications so listeners hear about dependent flags, not only the item that changed directly.

The FDv2 Store was feeding the dependency tracker symbol collection keys while prerequisite and segment references in the graph use strings, so add_affected_items never matched dependents. The store now passes key.to_s into the tracker for deltas, full-data resets, and full-set change detection (in-memory keys stay symbols).

Adds Store specs that apply symbol-keyed changes and assert notified flag keys for prerequisite chains, segment rules, newly added dependencies, and full transfers.

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

The FDv2 store passed change keys to the dependency tracker as symbols.
The tracker records dependents under the string keys that prerequisite
and segment references use, so a change never reached the flags that
depend on it. The store now converts keys to strings before it uses the
tracker, as the FDv1 data source update sink does.
@kinyoklion
kinyoklion marked this pull request as ready for review October 22, 2026 23:02
@kinyoklion
kinyoklion requested a review from a team as a code owner October 22, 2026 23:02
kinyoklion added a commit to launchdarkly/sdk-test-harness that referenced this pull request Oct 23, 2026
## Summary

The flag change listener tests only ever changed the flag that the
listener was watching, so an SDK that never notified dependent flags
passed them all. This adds a `dependent flags` group under both listener
suites.

The tests start the SDK with one data set: a three-flag prerequisite
chain, a flag whose rule references a segment, a flag whose prerequisite
is that segment-rule flag (so a segment change must travel through a
prerequisite), a flag whose rule references a segment that itself
matches a nested segment, and an unrelated flag. They then change a
prerequisite or a segment through the FDv2 stream and assert the exact
set of flags that a general flag change listener hears about, and
nothing else: the prerequisite chain, a change in the middle of it,
deletion of a prerequisite, segment and nested segment changes and
deletion (reaching the flag that depends on the segment-rule flag as
well), a dependency added or removed by an update, and a full data set
that changes or drops items. The flag value change listener tests assert
the value that a dependency change produces (prerequisite failing,
prerequisite deleted, segment starting to include the context, the same
through a prerequisite, nested segment) and that a change which leaves
the value as it was stays quiet.

New helpers: `ExpectFlagChangeNotifications` collects one notification
per expected key, compares the keys as a set, and then requires silence;
`registerFlagChangeListener` and `registerFlagValueChangeListener`
register a listener and close its callback when the test scope exits;
`streamPusher` pushes puts, deletes, and full data sets with
monotonically increasing versions. No change to the test service
protocol.

## Verification

Run locally against the current test services: Go (reference), Node,
Python, and .NET pass every new test. Ruby `main` fails exactly the 15
dependency tests and still passes the 8 existing direct-change tests,
which is the defect that launchdarkly/ruby-server-sdk#470 fixes; the
Ruby branch with that fix passes. The Java test service does not declare
the listener capabilities, so the suite is skipped there. `make lint`
and `go test ./...` are clean.

[SDK-3355](https://launchdarkly.atlassian.net/browse/SDK-3355)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> Adds **dependent flags** coverage to the SDK test harness listener
suites so SDKs must notify flags affected by prerequisite chains,
segment rules, nested segments, and full payload replacements—not only
the flag that was directly updated.
> 
> A new `common_tests_listeners_dependencies.go` drives FDv2 stream
updates (puts, deletes, full xfer) against a shared fixture
(prerequisite chain `top → mid → leaf`, segment-linked flags, nested
segments, unrelated control). **Flag change** tests assert the exact set
of notified flag keys; **flag value** tests assert old/new values when a
dependency changes evaluation and silence when it does not.
> 
> Test API helpers add `registerFlagChangeListener` /
`registerFlagValueChangeListener` (auto-close on scope exit),
`ExpectFlagChangeNotifications` (order-independent set match plus no
extra notifications), and `streamPusher` for monotonic versioning. No
change to the test service protocol.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
89bfbea. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

[SDK-3355]:
https://launchdarkly.atlassian.net/browse/SDK-3355?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
@kinyoklion
kinyoklion merged commit 6d79abe into main Oct 23, 2026
13 checks passed
@kinyoklion
kinyoklion deleted the rlamb/fdv2-store-dependency-keys branch October 23, 2026 19:43
kinyoklion pushed a commit that referenced this pull request Oct 23, 2026
🤖 I have created a release *beep* *boop*
---


##
[8.19.1](8.19.0...8.19.1)
(2026-10-23)


### Bug Fixes

* Notify dependent flags when an FDv2 prerequisite or segment changes
([#470](#470))
([6d79abe](6d79abe))

---
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**
> **Patch release 8.19.1** bumps the SDK from `8.19.0` to `8.19.1` via
Release Please (`LaunchDarkly::VERSION`,
`.release-please-manifest.json`, and the provenance doc example).
> 
> The changelog records one shipped fix
([#470](#470)):
**dependent flags are notified when an FDv2 prerequisite or segment
changes**, so flag-change listeners and related updates stay in sync
when upstream FDv2 data changes. This PR does not include application
code—only version and release metadata.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
df13a28. 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