Skip to content

Conversation

@jsonbailey
Copy link
Contributor

@jsonbailey jsonbailey commented Jan 8, 2026

Note

Introduces an FDv2-compatible in-memory test data source with dynamic updates.

  • Adds TestDataV2 to manage test flags, provide flag builders, update propagation, versioning, and to build FDv2 initializer/synchronizer
  • Implements TestDataSourceV2 that fulfills Initializer and Synchronizer, emitting initial full ChangeSet and incremental updates via a queue; supports stop and error signaling
  • Adds FlagBuilderV2 and FlagRuleBuilderV2 to define variations, targets, and simple "in/not in" rules, producing FDv2-compatible flag hashes

Written by Cursor Bugbot for commit 5003b43. This will update automatically on new commits. Configure here.

@jsonbailey jsonbailey requested a review from a team as a code owner January 8, 2026 16:09
until @closed
begin
# stop() will push nil to the queue to wake us up when shutting down
update = @update_queue.pop
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@keelerm84 Ruby doesn't have a pop with timeout like we do in Python. The stop method will push nil into the queue to stop it from blocking so I'm not sure it is needed but I wanted to call it out.

end

instances_copy.each do |instance|
instance.upsert_flag(new_flag)
Copy link

Choose a reason for hiding this comment

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

Variable scoped to block but used outside

High Severity

The new_flag variable is defined inside the with_write_lock block on line 121, but it's used outside the block on line 131. In Ruby, variables defined inside a block are local to that block and not accessible outside. This will cause a NameError at runtime when update is called. The original test_data.rb correctly handles this by defining new_flag = nil before the block.

Fix in Cursor Fix in Web


private def add_rule(flag_rule_builder)
@_rules << flag_rule_builder
end
Copy link

Choose a reason for hiding this comment

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

Private method called with explicit receiver fails

High Severity

The add_rule method is defined as private def add_rule(...), but it's called from FlagRuleBuilderV2#then_return with an explicit receiver (@_flag_builder.add_rule(self)). In Ruby, private methods cannot be called with an explicit receiver from a different object, which will cause a NoMethodError at runtime. The original flag_builder.rb correctly makes add_rule a public method (only marked with # @api private comment).

Additional Locations (1)

Fix in Cursor Fix in Web

# Add all flags to the changeset
init_data.each do |key, flag_data|
builder.add_put(
LaunchDarkly::Interfaces::DataSystem::ObjectKind::FLAG,
Copy link
Member

Choose a reason for hiding this comment

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

Should you be considering segments as well?

It looks like the old test data might have supported both flags and segments. Did we lose some functionality during this update?

# consider it part of the public API, but it is still called from TestDataV2.
#
# Creates a deep copy of the flag builder. Subsequent updates to the
# original `FlagBuilderV2` object will not update the copy and vise versa.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
# original `FlagBuilderV2` object will not update the copy and vise versa.
# original `FlagBuilderV2` object will not update the copy and vice versa.

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.

3 participants