Repository navigation
feat!: Make data kinds public and add SerializedItemDescriptor - #480
Merged
Merged
Conversation
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
marked this pull request as ready for review
November 4, 2026 18:21
kinyoklion
approved these changes
Nov 4, 2026
kinyoklion
left a comment
Member
There was a problem hiding this comment.
- 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?.
- 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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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, andALL_KINDSnow live onLaunchDarkly::Interfaces::DataStoreinstead ofLaunchDarkly::Impl::DataStore. The internalimpl/data_store.rbbarrel file is removed; impl code that still needs status plumbing loadsimpl/data_store/statusonly.The public
DataKindaddsserialize/deserialize(wrapping the model layer) so persistent-store gems can stay on public types, plusSerializedItemDescriptor(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
DataKindmove fromspec/impl/data_store_spec.rbtospec/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.