From 4b90c9e1e0f7e8deadfa51c6aeee8a7bb6c77de4 Mon Sep 17 00:00:00 2001 From: Matthew Keeler Date: Thu, 6 Jun 2024 12:17:51 -0400 Subject: [PATCH] fix: Increment flag & segment versions when reloading from file data source The file data source allows specifying flag information as a full flag definition, or as a shorted map of flag key:value mappings. In the case of the flag values, or in the case of a malformed flag definition, a flag version might not be specified. When this happens, users of the flag tracker will notice an error because the version comparison code will encounter an unexpected nil value. To prevent this from happening, the file data source should be setting a version for each flag or segment it reads. When these items are modified in the LaunchDarkly UI, we automatically increment the version associated with the item. To make this easier for the user going forward, the file data source will handle incrementing this version number each time the file is re-read. --- .../impl/integrations/file_data_source.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/ldclient-rb/impl/integrations/file_data_source.rb b/lib/ldclient-rb/impl/integrations/file_data_source.rb index c5ee917f..1e7ad078 100644 --- a/lib/ldclient-rb/impl/integrations/file_data_source.rb +++ b/lib/ldclient-rb/impl/integrations/file_data_source.rb @@ -40,6 +40,9 @@ def initialize(data_store, data_source_update_sink, logger, options={}) @poll_interval = options[:poll_interval] || 1 @initialized = Concurrent::AtomicBoolean.new(false) @ready = Concurrent::Event.new + + @version_lock = Mutex.new + @last_version = 1 end def initialized? @@ -93,14 +96,22 @@ def load_all end def load_file(path, all_data) + version = 1 + @version_lock.synchronize { + version = @last_version + @last_version += 1 + } + parsed = parse_content(IO.read(path)) (parsed[:flags] || {}).each do |key, flag| + flag[:version] = version add_item(all_data, FEATURES, flag) end (parsed[:flagValues] || {}).each do |key, value| - add_item(all_data, FEATURES, make_flag_with_value(key.to_s, value)) + add_item(all_data, FEATURES, make_flag_with_value(key.to_s, value, version)) end (parsed[:segments] || {}).each do |key, segment| + segment[:version] = version add_item(all_data, SEGMENTS, segment) end end @@ -134,10 +145,11 @@ def add_item(all_data, kind, item) items[key] = Model.deserialize(kind, item) end - def make_flag_with_value(key, value) + def make_flag_with_value(key, value, version) { key: key, on: true, + version: version, fallthrough: { variation: 0 }, variations: [ value ], }