Skip to content

feat: Add FDv2 payload application primitives#299

Draft
kinyoklion wants to merge 1 commit into
mainfrom
rlamb/sdk-2186/fdv2-payload-application
Draft

feat: Add FDv2 payload application primitives#299
kinyoklion wants to merge 1 commit into
mainfrom
rlamb/sdk-2186/fdv2-payload-application

Conversation

@kinyoklion

@kinyoklion kinyoklion commented Jun 10, 2026

Copy link
Copy Markdown
Member

What this adds

Two pieces the FDv2 data pipeline (a later PR) needs to apply payloads to the flag store correctly. Nothing produces FDv2 payloads for the flag manager yet, so behavior is unchanged.

Envelope version is authoritative for flag-eval objects

The flag-eval mapper now parses objects with the put-object envelope version substituted in, replacing any in-object value. The FDv2 wire format moved versioning onto the envelope; live service objects carry only flagVersion:

{"key":"greekTest","kind":"flag-eval","version":420,
 "object":{"flagVersion":7,"value":true,"variation":0,"trackEvents":false}}

The previous parse required an in-object version, which made every real payload fail with "FDv2 payload contained invalid data." The contract test harness includes an in-object version in its mock data, which is why the suites did not catch it; verified against the live service. This matches the JS implementation, which spreads the object over version: update.version.

FlagManager.applyUpdates

Applies a set of updates from a partial payload without per-item version comparison, plumbed through FlagPersistence/FlagUpdater with a single change event for the affected keys and the usual cache write-through. FDv2 orders data at the payload level, so a lower envelope version must still apply — the existing upsert discards it as out-of-order, which is correct for FDv1 patches but wrong here (the harness's "ignores model version" test sends exactly this). Updates remain context-checked like upsert, and an empty update set changes nothing and skips the cache write.

Known pre-existing divergence, intentionally not addressed here

Change detection (FlagUpdater._hasChanged) compares evaluation details by value onlyLDEvaluationDetail.== ignores variationIndex and reason — so a variation- or reason-only change applies to the store without a FlagsChangedEvent, despite the event's documentation promising reason changes. This is shared behavior across init/upsert/applyUpdates (the JS SDK compares the whole descriptor) and predates this PR; fixing it here would mix a behavior change into otherwise-inert plumbing, so it is left for a separate change.

Testing

Mapper tests pin the live wire shape (no in-object version parses; envelope version wins over a differing in-object value), alongside the existing put/delete/unknown-kind coverage. Flag updater tests cover applying without version comparison, a single change event for the changed keys, tombstones applied through applyUpdates (stored and evented), and rejection of updates for an inactive context. Persistence-level tests assert a successful apply writes through to the cache, a rejected apply does not, and an empty apply skips the write.

SDK-2186

@kinyoklion

Copy link
Copy Markdown
Member Author

bugbot review

@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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 7367952. Configure here.

Two pieces the FDv2 pipeline needs to apply payloads correctly:

- The flag-eval mapper uses the put-object envelope version as the
  evaluation result version, replacing any in-object value. The live
  service objects carry only flagVersion; requiring an in-object
  version made real payloads unparseable.
- FlagManager.applyUpdates applies a set of updates without per-item
  version comparison, since FDv2 orders data at the payload level. A
  lower envelope version must still apply. An empty payload changes
  nothing and skips the cache write.

Nothing produces FDv2 payloads for the flag manager yet.
@kinyoklion kinyoklion force-pushed the rlamb/sdk-2186/fdv2-payload-application branch from 7367952 to 8abfec4 Compare June 10, 2026 23:45
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