11require 'concurrent'
22require "ldclient-rb/interfaces"
3+ require "ldclient-rb/impl/data_store/data_kind"
34
45module LaunchDarkly
56 module Impl
67 module DataStore
7- class DataKind
8- FEATURES = "features" . freeze
9- SEGMENTS = "segments" . freeze
10-
11- FEATURE_PREREQ_FN = lambda { |flag | ( flag [ :prerequisites ] || [ ] ) . map { |p | p [ :key ] } } . freeze
12-
13- attr_reader :namespace
14- attr_reader :priority
15-
16- #
17- # @param namespace [String]
18- # @param priority [Integer]
19- #
20- def initialize ( namespace :, priority :)
21- @namespace = namespace
22- @priority = priority
23- end
24-
8+ # These constants denote the types of data that can be stored in the feature store. If
9+ # we add another storable data type in the future, as long as it follows the same pattern
10+ # (having "key", "version", and "deleted" properties), we only need to add a corresponding
11+ # constant here and the existing store should be able to handle it.
2512 #
26- # Maintain the same behavior when these data kinds were standard ruby hashes.
27- #
28- # @param key [Symbol]
29- # @return [Object]
30- #
31- def []( key )
32- return priority if key == :priority
33- return namespace if key == :namespace
34- return get_dependency_keys_fn ( ) if key == :get_dependency_keys
35- nil
36- end
37-
38- #
39- # Retrieve the dependency keys for a particular data kind. Right now, this is only defined for flags.
40- #
41- def get_dependency_keys_fn ( )
42- return nil unless @namespace == FEATURES
43-
44- FEATURE_PREREQ_FN
45- end
46-
47- def eql? ( other )
48- other . is_a? ( DataKind ) && namespace == other . namespace && priority == other . priority
49- end
50-
51- def hash
52- [ namespace , priority ] . hash
53- end
54- end
55-
56- class StatusProvider
57- include LaunchDarkly ::Interfaces ::DataStore ::StatusProvider
58-
59- def initialize ( store , update_sink )
60- # @type [LaunchDarkly::Impl::FeatureStoreClientWrapper]
61- @store = store
62- # @type [UpdateSink]
63- @update_sink = update_sink
64- end
65-
66- def status
67- @update_sink . last_status . get
68- end
69-
70- def monitoring_enabled?
71- @store . monitoring_enabled?
72- end
73-
74- def add_listener ( listener )
75- @update_sink . broadcaster . add_listener ( listener )
76- end
77-
78- def remove_listener ( listener )
79- @update_sink . broadcaster . remove_listener ( listener )
80- end
81- end
82-
83- class UpdateSink
84- include LaunchDarkly ::Interfaces ::DataStore ::UpdateSink
85-
86- # @return [LaunchDarkly::Impl::Broadcaster]
87- attr_reader :broadcaster
88-
89- # @return [Concurrent::AtomicReference]
90- attr_reader :last_status
13+ # The :priority and :get_dependency_keys properties are used by FeatureStoreDataSetSorter
14+ # to ensure data consistency during non-atomic updates.
9115
92- def initialize ( broadcaster )
93- @broadcaster = broadcaster
94- @last_status = Concurrent ::AtomicReference . new (
95- LaunchDarkly ::Interfaces ::DataStore ::Status . new ( true , false )
96- )
97- end
16+ # @api private
17+ FEATURES = DataKind . new ( namespace : "features" , priority : 1 ) . freeze
9818
99- def update_status ( status )
100- return if status . nil?
19+ # @api private
20+ SEGMENTS = DataKind . new ( namespace : "segments" , priority : 0 ) . freeze
10121
102- old_status = @last_status . get_and_set ( status )
103- @broadcaster . broadcast ( status ) unless old_status == status
104- end
105- end
22+ # @api private
23+ ALL_KINDS = [ FEATURES , SEGMENTS ] . freeze
10624 end
10725 end
108- end
26+ end
0 commit comments