launchdarkly-server-sdk 6.2.5 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -2
  3. data/lib/ldclient-rb/config.rb +203 -43
  4. data/lib/ldclient-rb/context.rb +487 -0
  5. data/lib/ldclient-rb/evaluation_detail.rb +85 -26
  6. data/lib/ldclient-rb/events.rb +185 -146
  7. data/lib/ldclient-rb/flags_state.rb +25 -14
  8. data/lib/ldclient-rb/impl/big_segments.rb +117 -0
  9. data/lib/ldclient-rb/impl/context.rb +96 -0
  10. data/lib/ldclient-rb/impl/context_filter.rb +145 -0
  11. data/lib/ldclient-rb/impl/diagnostic_events.rb +9 -10
  12. data/lib/ldclient-rb/impl/evaluator.rb +428 -132
  13. data/lib/ldclient-rb/impl/evaluator_bucketing.rb +40 -41
  14. data/lib/ldclient-rb/impl/evaluator_helpers.rb +50 -0
  15. data/lib/ldclient-rb/impl/evaluator_operators.rb +26 -55
  16. data/lib/ldclient-rb/impl/event_sender.rb +6 -6
  17. data/lib/ldclient-rb/impl/event_summarizer.rb +68 -0
  18. data/lib/ldclient-rb/impl/event_types.rb +78 -0
  19. data/lib/ldclient-rb/impl/integrations/consul_impl.rb +7 -7
  20. data/lib/ldclient-rb/impl/integrations/dynamodb_impl.rb +92 -28
  21. data/lib/ldclient-rb/impl/integrations/file_data_source.rb +212 -0
  22. data/lib/ldclient-rb/impl/integrations/redis_impl.rb +165 -32
  23. data/lib/ldclient-rb/impl/integrations/test_data/test_data_source.rb +40 -0
  24. data/lib/ldclient-rb/impl/model/clause.rb +39 -0
  25. data/lib/ldclient-rb/impl/model/feature_flag.rb +213 -0
  26. data/lib/ldclient-rb/impl/model/preprocessed_data.rb +64 -0
  27. data/lib/ldclient-rb/impl/model/segment.rb +126 -0
  28. data/lib/ldclient-rb/impl/model/serialization.rb +54 -44
  29. data/lib/ldclient-rb/impl/repeating_task.rb +47 -0
  30. data/lib/ldclient-rb/impl/store_data_set_sorter.rb +2 -2
  31. data/lib/ldclient-rb/impl/unbounded_pool.rb +1 -1
  32. data/lib/ldclient-rb/impl/util.rb +62 -1
  33. data/lib/ldclient-rb/in_memory_store.rb +2 -2
  34. data/lib/ldclient-rb/integrations/consul.rb +9 -2
  35. data/lib/ldclient-rb/integrations/dynamodb.rb +47 -2
  36. data/lib/ldclient-rb/integrations/file_data.rb +108 -0
  37. data/lib/ldclient-rb/integrations/redis.rb +43 -3
  38. data/lib/ldclient-rb/integrations/test_data/flag_builder.rb +594 -0
  39. data/lib/ldclient-rb/integrations/test_data.rb +213 -0
  40. data/lib/ldclient-rb/integrations/util/store_wrapper.rb +14 -9
  41. data/lib/ldclient-rb/integrations.rb +2 -51
  42. data/lib/ldclient-rb/interfaces.rb +151 -1
  43. data/lib/ldclient-rb/ldclient.rb +175 -133
  44. data/lib/ldclient-rb/memoized_value.rb +1 -1
  45. data/lib/ldclient-rb/non_blocking_thread_pool.rb +1 -1
  46. data/lib/ldclient-rb/polling.rb +22 -41
  47. data/lib/ldclient-rb/reference.rb +274 -0
  48. data/lib/ldclient-rb/requestor.rb +7 -7
  49. data/lib/ldclient-rb/stream.rb +9 -9
  50. data/lib/ldclient-rb/util.rb +11 -17
  51. data/lib/ldclient-rb/version.rb +1 -1
  52. data/lib/ldclient-rb.rb +2 -4
  53. metadata +49 -23
  54. data/lib/ldclient-rb/event_summarizer.rb +0 -55
  55. data/lib/ldclient-rb/file_data_source.rb +0 -314
  56. data/lib/ldclient-rb/impl/event_factory.rb +0 -126
  57. data/lib/ldclient-rb/newrelic.rb +0 -17
  58. data/lib/ldclient-rb/redis_store.rb +0 -88
  59. data/lib/ldclient-rb/user_filter.rb +0 -52
@@ -0,0 +1,213 @@
1
+ require 'ldclient-rb/impl/integrations/test_data/test_data_source'
2
+ require 'ldclient-rb/impl/model/feature_flag'
3
+ require 'ldclient-rb/impl/model/segment'
4
+ require 'ldclient-rb/integrations/test_data/flag_builder'
5
+
6
+ require 'concurrent/atomics'
7
+
8
+ module LaunchDarkly
9
+ module Integrations
10
+ #
11
+ # A mechanism for providing dynamically updatable feature flag state in a simplified form to an SDK
12
+ # client in test scenarios.
13
+ #
14
+ # Unlike {LaunchDarkly::Integrations::FileData}, this mechanism does not use any external resources. It
15
+ # provides only the data that the application has put into it using the {#update} method.
16
+ #
17
+ # @example
18
+ # td = LaunchDarkly::Integrations::TestData.data_source
19
+ # td.update(td.flag("flag-key-1").variation_for_all(true))
20
+ # config = LaunchDarkly::Config.new(data_source: td)
21
+ # client = LaunchDarkly::LDClient.new('sdkKey', config)
22
+ # # flags can be updated at any time:
23
+ # td.update(td.flag("flag-key-2")
24
+ # .variation_for_key("user", some-user-key", true)
25
+ # .fallthrough_variation(false))
26
+ #
27
+ # The above example uses a simple boolean flag, but more complex configurations are possible using
28
+ # the methods of the {FlagBuilder} that is returned by {#flag}. {FlagBuilder}
29
+ # supports many of the ways a flag can be configured on the LaunchDarkly dashboard, but does not
30
+ # currently support 1. rule operators other than "in" and "not in", or 2. percentage rollouts.
31
+ #
32
+ # If the same `TestData` instance is used to configure multiple `LDClient` instances,
33
+ # any changes made to the data will propagate to all of the `LDClient`s.
34
+ #
35
+ # @since 6.3.0
36
+ #
37
+ class TestData
38
+ # Creates a new instance of the test data source.
39
+ #
40
+ # @return [TestData] a new configurable test data source
41
+ def self.data_source
42
+ self.new
43
+ end
44
+
45
+ # @private
46
+ def initialize
47
+ @flag_builders = Hash.new
48
+ @current_flags = Hash.new
49
+ @current_segments = Hash.new
50
+ @instances = Array.new
51
+ @instances_lock = Concurrent::ReadWriteLock.new
52
+ @lock = Concurrent::ReadWriteLock.new
53
+ end
54
+
55
+ #
56
+ # Called internally by the SDK to determine what arguments to pass to call
57
+ # You do not need to call this method.
58
+ #
59
+ # @private
60
+ def arity
61
+ 2
62
+ end
63
+
64
+ #
65
+ # Called internally by the SDK to associate this test data source with an {@code LDClient} instance.
66
+ # You do not need to call this method.
67
+ #
68
+ # @private
69
+ def call(_, config)
70
+ impl = LaunchDarkly::Impl::Integrations::TestData::TestDataSource.new(config.feature_store, self)
71
+ @instances_lock.with_write_lock { @instances.push(impl) }
72
+ impl
73
+ end
74
+
75
+ #
76
+ # Creates or copies a {FlagBuilder} for building a test flag configuration.
77
+ #
78
+ # If this flag key has already been defined in this `TestData` instance, then the builder
79
+ # starts with the same configuration that was last provided for this flag.
80
+ #
81
+ # Otherwise, it starts with a new default configuration in which the flag has `true` and
82
+ # `false` variations, is `true` for all contexts when targeting is turned on and
83
+ # `false` otherwise, and currently has targeting turned on. You can change any of those
84
+ # properties, and provide more complex behavior, using the {FlagBuilder} methods.
85
+ #
86
+ # Once you have set the desired configuration, pass the builder to {#update}.
87
+ #
88
+ # @param key [String] the flag key
89
+ # @return [FlagBuilder] a flag configuration builder
90
+ #
91
+ def flag(key)
92
+ existing_builder = @lock.with_read_lock { @flag_builders[key] }
93
+ if existing_builder.nil? then
94
+ FlagBuilder.new(key).boolean_flag
95
+ else
96
+ existing_builder.clone
97
+ end
98
+ end
99
+
100
+ #
101
+ # Updates the test data with the specified flag configuration.
102
+ #
103
+ # This has the same effect as if a flag were added or modified on the LaunchDarkly dashboard.
104
+ # It immediately propagates the flag change to any `LDClient` instance(s) that you have
105
+ # already configured to use this `TestData`. If no `LDClient` has been started yet,
106
+ # it simply adds this flag to the test data which will be provided to any `LDClient` that
107
+ # you subsequently configure.
108
+ #
109
+ # Any subsequent changes to this {FlagBuilder} instance do not affect the test data,
110
+ # unless you call {#update} again.
111
+ #
112
+ # @param flag_builder [FlagBuilder] a flag configuration builder
113
+ # @return [TestData] the TestData instance
114
+ #
115
+ def update(flag_builder)
116
+ new_flag = nil
117
+ @lock.with_write_lock do
118
+ @flag_builders[flag_builder.key] = flag_builder
119
+ version = 0
120
+ flag_key = flag_builder.key.to_sym
121
+ if @current_flags[flag_key] then
122
+ version = @current_flags[flag_key][:version]
123
+ end
124
+ new_flag = Impl::Model.deserialize(FEATURES, flag_builder.build(version+1))
125
+ @current_flags[flag_key] = new_flag
126
+ end
127
+ update_item(FEATURES, new_flag)
128
+ self
129
+ end
130
+
131
+ #
132
+ # Copies a full feature flag data model object into the test data.
133
+ #
134
+ # It immediately propagates the flag change to any `LDClient` instance(s) that you have already
135
+ # configured to use this `TestData`. If no `LDClient` has been started yet, it simply adds
136
+ # this flag to the test data which will be provided to any LDClient that you subsequently
137
+ # configure.
138
+ #
139
+ # Use this method if you need to use advanced flag configuration properties that are not supported by
140
+ # the simplified {FlagBuilder} API. Otherwise it is recommended to use the regular {flag}/{update}
141
+ # mechanism to avoid dependencies on details of the data model.
142
+ #
143
+ # You cannot make incremental changes with {flag}/{update} to a flag that has been added in this way;
144
+ # you can only replace it with an entirely new flag configuration.
145
+ #
146
+ # @param flag [Hash] the flag configuration
147
+ # @return [TestData] the TestData instance
148
+ #
149
+ def use_preconfigured_flag(flag)
150
+ use_preconfigured_item(FEATURES, flag, @current_flags)
151
+ end
152
+
153
+ #
154
+ # Copies a full segment data model object into the test data.
155
+ #
156
+ # It immediately propagates the change to any `LDClient` instance(s) that you have already
157
+ # configured to use this `TestData`. If no `LDClient` has been started yet, it simply adds
158
+ # this segment to the test data which will be provided to any LDClient that you subsequently
159
+ # configure.
160
+ #
161
+ # This method is currently the only way to inject segment data, since there is no builder
162
+ # API for segments. It is mainly intended for the SDK's own tests of segment functionality,
163
+ # since application tests that need to produce a desired evaluation state could do so more easily
164
+ # by just setting flag values.
165
+ #
166
+ # @param segment [Hash] the segment configuration
167
+ # @return [TestData] the TestData instance
168
+ #
169
+ def use_preconfigured_segment(segment)
170
+ use_preconfigured_item(SEGMENTS, segment, @current_segments)
171
+ end
172
+
173
+ private def use_preconfigured_item(kind, item, current)
174
+ item = Impl::Model.deserialize(kind, item)
175
+ key = item.key.to_sym
176
+ @lock.with_write_lock do
177
+ old_item = current[key]
178
+ unless old_item.nil? then
179
+ data = item.as_json
180
+ data[:version] = old_item.version + 1
181
+ item = Impl::Model.deserialize(kind, data)
182
+ end
183
+ current[key] = item
184
+ end
185
+ update_item(kind, item)
186
+ self
187
+ end
188
+
189
+ private def update_item(kind, item)
190
+ @instances_lock.with_read_lock do
191
+ @instances.each do | instance |
192
+ instance.upsert(kind, item)
193
+ end
194
+ end
195
+ end
196
+
197
+ # @private
198
+ def make_init_data
199
+ @lock.with_read_lock do
200
+ {
201
+ FEATURES => @current_flags.clone,
202
+ SEGMENTS => @current_segments.clone,
203
+ }
204
+ end
205
+ end
206
+
207
+ # @private
208
+ def closed_instance(instance)
209
+ @instances_lock.with_write_lock { @instances.delete(instance) }
210
+ end
211
+ end
212
+ end
213
+ end
@@ -4,6 +4,11 @@ require "ldclient-rb/expiring_cache"
4
4
 
5
5
  module LaunchDarkly
6
6
  module Integrations
7
+ #
8
+ # Support code that may be helpful in creating integrations.
9
+ #
10
+ # @since 5.5.0
11
+ #
7
12
  module Util
8
13
  #
9
14
  # CachingStoreWrapper is a partial implementation of the {LaunchDarkly::Interfaces::FeatureStore}
@@ -17,7 +22,7 @@ module LaunchDarkly
17
22
  #
18
23
  class CachingStoreWrapper
19
24
  include LaunchDarkly::Interfaces::FeatureStore
20
-
25
+
21
26
  #
22
27
  # Creates a new store wrapper instance.
23
28
  #
@@ -44,7 +49,7 @@ module LaunchDarkly
44
49
  @core.init_internal(all_data)
45
50
  @inited.make_true
46
51
 
47
- if !@cache.nil?
52
+ unless @cache.nil?
48
53
  @cache.clear
49
54
  all_data.each do |kind, items|
50
55
  @cache[kind] = items_if_not_deleted(items)
@@ -56,15 +61,15 @@ module LaunchDarkly
56
61
  end
57
62
 
58
63
  def get(kind, key)
59
- if !@cache.nil?
64
+ unless @cache.nil?
60
65
  cache_key = item_cache_key(kind, key)
61
66
  cached = @cache[cache_key] # note, item entries in the cache are wrapped in an array so we can cache nil values
62
- return item_if_not_deleted(cached[0]) if !cached.nil?
67
+ return item_if_not_deleted(cached[0]) unless cached.nil?
63
68
  end
64
69
 
65
70
  item = @core.get_internal(kind, key)
66
71
 
67
- if !@cache.nil?
72
+ unless @cache.nil?
68
73
  @cache[cache_key] = [item]
69
74
  end
70
75
 
@@ -72,20 +77,20 @@ module LaunchDarkly
72
77
  end
73
78
 
74
79
  def all(kind)
75
- if !@cache.nil?
80
+ unless @cache.nil?
76
81
  items = @cache[all_cache_key(kind)]
77
- return items if !items.nil?
82
+ return items unless items.nil?
78
83
  end
79
84
 
80
85
  items = items_if_not_deleted(@core.get_all_internal(kind))
81
- @cache[all_cache_key(kind)] = items if !@cache.nil?
86
+ @cache[all_cache_key(kind)] = items unless @cache.nil?
82
87
  items
83
88
  end
84
89
 
85
90
  def upsert(kind, item)
86
91
  new_state = @core.upsert_internal(kind, item)
87
92
 
88
- if !@cache.nil?
93
+ unless @cache.nil?
89
94
  @cache[item_cache_key(kind, item[:key])] = [new_state]
90
95
  @cache.delete(all_cache_key(kind))
91
96
  end
@@ -1,55 +1,6 @@
1
1
  require "ldclient-rb/integrations/consul"
2
2
  require "ldclient-rb/integrations/dynamodb"
3
+ require "ldclient-rb/integrations/file_data"
3
4
  require "ldclient-rb/integrations/redis"
5
+ require "ldclient-rb/integrations/test_data"
4
6
  require "ldclient-rb/integrations/util/store_wrapper"
5
-
6
- module LaunchDarkly
7
- #
8
- # Tools for connecting the LaunchDarkly client to other software.
9
- #
10
- module Integrations
11
- #
12
- # Integration with [Consul](https://www.consul.io/).
13
- #
14
- # Note that in order to use this integration, you must first install the gem `diplomat`.
15
- #
16
- # @since 5.5.0
17
- #
18
- module Consul
19
- # code is in ldclient-rb/impl/integrations/consul_impl
20
- end
21
-
22
- #
23
- # Integration with [DynamoDB](https://aws.amazon.com/dynamodb/).
24
- #
25
- # Note that in order to use this integration, you must first install one of the AWS SDK gems: either
26
- # `aws-sdk-dynamodb`, or the full `aws-sdk`.
27
- #
28
- # @since 5.5.0
29
- #
30
- module DynamoDB
31
- # code is in ldclient-rb/impl/integrations/dynamodb_impl
32
- end
33
-
34
- #
35
- # Integration with [Redis](https://redis.io/).
36
- #
37
- # Note that in order to use this integration, you must first install the `redis` and `connection-pool`
38
- # gems.
39
- #
40
- # @since 5.5.0
41
- #
42
- module Redis
43
- # code is in ldclient-rb/impl/integrations/redis_impl
44
- end
45
-
46
- #
47
- # Support code that may be helpful in creating integrations.
48
- #
49
- # @since 5.5.0
50
- #
51
- module Util
52
- # code is in ldclient-rb/integrations/util/
53
- end
54
- end
55
- end
@@ -1,3 +1,4 @@
1
+ require "observer"
1
2
 
2
3
  module LaunchDarkly
3
4
  #
@@ -120,7 +121,8 @@ module LaunchDarkly
120
121
  #
121
122
  # The client has its own standard implementation, which uses either a streaming connection or
122
123
  # polling depending on your configuration. Normally you will not need to use another one
123
- # except for testing purposes. {FileDataSource} provides one such test fixture.
124
+ # except for testing purposes. Two such test fixtures are {LaunchDarkly::Integrations::FileData}
125
+ # and {LaunchDarkly::Integrations::TestData}.
124
126
  #
125
127
  module DataSource
126
128
  #
@@ -149,5 +151,153 @@ module LaunchDarkly
149
151
  def stop
150
152
  end
151
153
  end
154
+
155
+ module BigSegmentStore
156
+ #
157
+ # Returns information about the overall state of the store. This method will be called only
158
+ # when the SDK needs the latest state, so it should not be cached.
159
+ #
160
+ # @return [BigSegmentStoreMetadata]
161
+ #
162
+ def get_metadata
163
+ end
164
+
165
+ #
166
+ # Queries the store for a snapshot of the current segment state for a specific context.
167
+ #
168
+ # The context_hash is a base64-encoded string produced by hashing the context key as defined by
169
+ # the Big Segments specification; the store implementation does not need to know the details
170
+ # of how this is done, because it deals only with already-hashed keys, but the string can be
171
+ # assumed to only contain characters that are valid in base64.
172
+ #
173
+ # The return value should be either a Hash, or nil if the context is not referenced in any big
174
+ # segments. Each key in the Hash is a "segment reference", which is how segments are
175
+ # identified in Big Segment data. This string is not identical to the segment key-- the SDK
176
+ # will add other information. The store implementation should not be concerned with the
177
+ # format of the string. Each value in the Hash is true if the context is explicitly included in
178
+ # the segment, false if the context is explicitly excluded from the segment-- and is not also
179
+ # explicitly included (that is, if both an include and an exclude existed in the data, the
180
+ # include would take precedence). If the context's status in a particular segment is undefined,
181
+ # there should be no key or value for that segment.
182
+ #
183
+ # This Hash may be cached by the SDK, so it should not be modified after it is created. It
184
+ # is a snapshot of the segment membership state at one point in time.
185
+ #
186
+ # @param context_hash [String]
187
+ # @return [Hash] true/false values for Big Segments that reference this context
188
+ #
189
+ def get_membership(context_hash)
190
+ end
191
+
192
+ #
193
+ # Performs any necessary cleanup to shut down the store when the client is being shut down.
194
+ #
195
+ # @return [void]
196
+ #
197
+ def stop
198
+ end
199
+ end
200
+
201
+ #
202
+ # Values returned by {BigSegmentStore#get_metadata}.
203
+ #
204
+ class BigSegmentStoreMetadata
205
+ def initialize(last_up_to_date)
206
+ @last_up_to_date = last_up_to_date
207
+ end
208
+
209
+ # The Unix epoch millisecond timestamp of the last update to the {BigSegmentStore}. It is
210
+ # nil if the store has never been updated.
211
+ #
212
+ # @return [Integer|nil]
213
+ attr_reader :last_up_to_date
214
+ end
215
+
216
+ #
217
+ # Information about the status of a Big Segment store, provided by {BigSegmentStoreStatusProvider}.
218
+ #
219
+ # Big Segments are a specific type of segments. For more information, read the LaunchDarkly
220
+ # documentation: https://docs.launchdarkly.com/home/users/big-segments
221
+ #
222
+ class BigSegmentStoreStatus
223
+ def initialize(available, stale)
224
+ @available = available
225
+ @stale = stale
226
+ end
227
+
228
+ # True if the Big Segment store is able to respond to queries, so that the SDK can evaluate
229
+ # whether a context is in a segment or not.
230
+ #
231
+ # If this property is false, the store is not able to make queries (for instance, it may not have
232
+ # a valid database connection). In this case, the SDK will treat any reference to a Big Segment
233
+ # as if no contexts are included in that segment. Also, the {EvaluationReason} associated with
234
+ # with any flag evaluation that references a Big Segment when the store is not available will
235
+ # have a `big_segments_status` of `STORE_ERROR`.
236
+ #
237
+ # @return [Boolean]
238
+ attr_reader :available
239
+
240
+ # True if the Big Segment store is available, but has not been updated within the amount of time
241
+ # specified by {BigSegmentsConfig#stale_after}.
242
+ #
243
+ # This may indicate that the LaunchDarkly Relay Proxy, which populates the store, has stopped
244
+ # running or has become unable to receive fresh data from LaunchDarkly. Any feature flag
245
+ # evaluations that reference a Big Segment will be using the last known data, which may be out
246
+ # of date. Also, the {EvaluationReason} associated with those evaluations will have a
247
+ # `big_segments_status` of `STALE`.
248
+ #
249
+ # @return [Boolean]
250
+ attr_reader :stale
251
+
252
+ def ==(other)
253
+ self.available == other.available && self.stale == other.stale
254
+ end
255
+ end
256
+
257
+ #
258
+ # An interface for querying the status of a Big Segment store.
259
+ #
260
+ # The Big Segment store is the component that receives information about Big Segments, normally
261
+ # from a database populated by the LaunchDarkly Relay Proxy. Big Segments are a specific type
262
+ # of segments. For more information, read the LaunchDarkly documentation:
263
+ # https://docs.launchdarkly.com/home/users/big-segments
264
+ #
265
+ # An implementation of this interface is returned by {LDClient#big_segment_store_status_provider}.
266
+ # Application code never needs to implement this interface.
267
+ #
268
+ # There are two ways to interact with the status. One is to simply get the current status; if its
269
+ # `available` property is true, then the SDK is able to evaluate context membership in Big Segments,
270
+ # and the `stale`` property indicates whether the data might be out of date.
271
+ #
272
+ # The other way is to subscribe to status change notifications. Applications may wish to know if
273
+ # there is an outage in the Big Segment store, or if it has become stale (the Relay Proxy has
274
+ # stopped updating it with new data), since then flag evaluations that reference a Big Segment
275
+ # might return incorrect values. To allow finding out about status changes as soon as possible,
276
+ # `BigSegmentStoreStatusProvider` mixes in Ruby's
277
+ # [Observable](https://docs.ruby-lang.org/en/2.5.0/Observable.html) module to provide standard
278
+ # methods such as `add_observer`. Observers will be called with a new {BigSegmentStoreStatus}
279
+ # value whenever the status changes.
280
+ #
281
+ # @example Getting the current status
282
+ # status = client.big_segment_store_status_provider.status
283
+ #
284
+ # @example Subscribing to status notifications
285
+ # client.big_segment_store_status_provider.add_observer(self, :big_segments_status_changed)
286
+ #
287
+ # def big_segments_status_changed(new_status)
288
+ # puts "Big segment store status is now: #{new_status}"
289
+ # end
290
+ #
291
+ module BigSegmentStoreStatusProvider
292
+ include Observable
293
+ #
294
+ # Gets the current status of the store, if known.
295
+ #
296
+ # @return [BigSegmentStoreStatus] the status, or nil if the SDK has not yet queried the Big
297
+ # Segment store status
298
+ #
299
+ def status
300
+ end
301
+ end
152
302
  end
153
303
  end