Skip to content

feat!: Make data kinds public and add SerializedItemDescriptor - #480

Merged
keelerm84 merged 5 commits into
feat/9.xfrom
mk/SDK-3453/public-data-kinds
Nov 4, 2026
Merged

keelerm84 merged 5 commits into
feat/9.xfrom
mk/SDK-3453/public-data-kinds

Conversation

@keelerm84

@keelerm84 keelerm84 commented Nov 3, 2026 •

Copy link
Copy Markdown
Member
  • feat: Make data kinds public and add SerializedItemDescriptor
    A persistent data store integration in its own gem can only use public SDK types. Today the data kinds live in LaunchDarkly::Impl::DataStore, and the Redis, DynamoDB and Consul cores call LaunchDarkly::Impl::Model.serialize and .deserialize directly.

    DataKind, FEATURES, SEGMENTS and ALL_KINDS move to LaunchDarkly::Interfaces::DataStore. DataKind gains serialize and deserialize, which match the DataKind serialization methods in the Go, Java and .NET SDKs. SerializedItemDescriptor (version, deleted, serialized_item) matches the type that the persistent data store interface takes in those SDKs and in js-core.

    The Impl names stay as aliases, so no SDK code changes. A later change adds the persistent data store interface that uses these types.

  • feat!: Remove the Impl::DataStore data kind aliases
    The data kinds are now public in LaunchDarkly::Interfaces::DataStore. The LaunchDarkly::Impl::DataStore names for DataKind, FEATURES, SEGMENTS and ALL_KINDS were internal and had no compatibility guarantee, but the FDv2 store interface docs told store authors to use them. Code that used those names must use the LaunchDarkly::Interfaces::DataStore names instead.

    All SDK code now uses the public names. ldclient-rb/impl/data_store.rb is gone, and ldclient-rb/impl/data_store/data_kind.rb, which now holds only the status provider and update sink, is renamed to status.rb.


Note

Overview
Breaking change: DataKind, FEATURES, SEGMENTS, and ALL_KINDS now live on LaunchDarkly::Interfaces::DataStore instead of LaunchDarkly::Impl::DataStore. The internal impl/data_store.rb barrel file is removed; impl code that still needs status plumbing loads impl/data_store/status only.

The public DataKind adds serialize / deserialize (wrapping the model layer) so persistent-store gems can stay on public types, plus SerializedItemDescriptor (version, deleted, serialized_item) aligned with other SDKs. Hash-style [] access and equality/hash behavior are preserved for ordering and dependency tracking.

Every data path in the SDK (streaming/polling updates, FDv1/FDv2 store, file/test data sources, dependency tracker, client reads) now references the Interfaces constants. Specs for DataKind move from spec/impl/data_store_spec.rb to spec/interfaces/data_store_spec.rb, including round-trip serialization and a load-isolated require check.

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

A persistent data store integration in its own gem can only use public SDK types. Today the data kinds live in LaunchDarkly::Impl::DataStore, and the Redis, DynamoDB and Consul cores call LaunchDarkly::Impl::Model.serialize and .deserialize directly.

DataKind, FEATURES, SEGMENTS and ALL_KINDS move to LaunchDarkly::Interfaces::DataStore. DataKind gains serialize and deserialize, which match the DataKind serialization methods in the Go, Java and .NET SDKs. SerializedItemDescriptor (version, deleted, serialized_item) matches the type that the persistent data store interface takes in those SDKs and in js-core.

The Impl names stay as aliases, so no SDK code changes. A later change adds the persistent data store interface that uses these types.
The data kinds are now public in LaunchDarkly::Interfaces::DataStore. The LaunchDarkly::Impl::DataStore names for DataKind, FEATURES, SEGMENTS and ALL_KINDS were internal and had no compatibility guarantee, but the FDv2 store interface docs told store authors to use them. Code that used those names must use the LaunchDarkly::Interfaces::DataStore names instead.

All SDK code now uses the public names. ldclient-rb/impl/data_store.rb is gone, and ldclient-rb/impl/data_store/data_kind.rb, which now holds only the status provider and update sink, is renamed to status.rb.
@keelerm84
keelerm84 marked this pull request as ready for review November 4, 2026 18:21
@keelerm84
keelerm84 requested a review from a team as a code owner November 4, 2026 18:21

@kinyoklion kinyoklion left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

  1. DataKind defines eql?/hash but not ==/=== — a reconstructed or Marshal'd kind is value-equal yet identity-unequal, so Model.deserialize's case/when silently returns a raw Hash instead of a FeatureFlag (also breaks ALL_KINDS.include?). In-SDK trigger CANNOT-PROVE (SDK uses only frozen constants); the hazard is for the new public audience the PR creates. Fix: alias_method :==, :eql?.
  2. interfaces/data_store.rb has no requires — under the public-types-only require the PR tells store-gem authors to use, serialize/deserialize raise NameError (and even with serialization manually required, NoMethodError on Hash#to_json — json never required). Only full require "ldclient-rb" works — defeats the PR's stated purpose in the gem-dev harness. Fix: two require lines (no circularity, verified).

…c-data-kinds

# Conflicts:
#	spec/impl/data_source_spec.rb
DataKind defined eql? and hash but not ==, so == fell back to identity.
A kind built with the same namespace and priority, or one restored with
Marshal, was not == to the SDK constant. Model.deserialize selects the
model class with case/when, so such a kind deserialized to a raw Hash
instead of a FeatureFlag or Segment, and ALL_KINDS.include? missed it.

Inside the SDK only the frozen constants reach these paths. Store gems
can now build or receive kinds themselves, so equality must be by value.
A store gem that required only ldclient-rb/interfaces/data_store got a
NameError from DataKind#serialize and #deserialize, because the file did
not load the model serialization code. The serialization code did not
load json, and the FeatureFlag and Segment models did not load
LDContext, so each of those failed next. Each file now requires what it
uses, and a spec loads the public file alone in a separate process.
@keelerm84
keelerm84 merged commit b145573 into feat/9.x Nov 4, 2026
14 of 15 checks passed
@keelerm84
keelerm84 deleted the mk/SDK-3453/public-data-kinds branch November 4, 2026 20:00
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