launchdarkly-server-sdk 6.1.1 → 6.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -5
  3. data/lib/ldclient-rb/config.rb +118 -4
  4. data/lib/ldclient-rb/evaluation_detail.rb +104 -14
  5. data/lib/ldclient-rb/events.rb +201 -107
  6. data/lib/ldclient-rb/file_data_source.rb +9 -300
  7. data/lib/ldclient-rb/flags_state.rb +23 -12
  8. data/lib/ldclient-rb/impl/big_segments.rb +117 -0
  9. data/lib/ldclient-rb/impl/diagnostic_events.rb +1 -1
  10. data/lib/ldclient-rb/impl/evaluator.rb +116 -62
  11. data/lib/ldclient-rb/impl/evaluator_bucketing.rb +22 -9
  12. data/lib/ldclient-rb/impl/evaluator_helpers.rb +53 -0
  13. data/lib/ldclient-rb/impl/evaluator_operators.rb +1 -1
  14. data/lib/ldclient-rb/impl/event_summarizer.rb +63 -0
  15. data/lib/ldclient-rb/impl/event_types.rb +90 -0
  16. data/lib/ldclient-rb/impl/integrations/dynamodb_impl.rb +82 -18
  17. data/lib/ldclient-rb/impl/integrations/file_data_source.rb +212 -0
  18. data/lib/ldclient-rb/impl/integrations/redis_impl.rb +84 -31
  19. data/lib/ldclient-rb/impl/integrations/test_data/test_data_source.rb +40 -0
  20. data/lib/ldclient-rb/impl/model/preprocessed_data.rb +177 -0
  21. data/lib/ldclient-rb/impl/model/serialization.rb +7 -37
  22. data/lib/ldclient-rb/impl/repeating_task.rb +47 -0
  23. data/lib/ldclient-rb/impl/util.rb +62 -1
  24. data/lib/ldclient-rb/integrations/consul.rb +8 -1
  25. data/lib/ldclient-rb/integrations/dynamodb.rb +48 -3
  26. data/lib/ldclient-rb/integrations/file_data.rb +108 -0
  27. data/lib/ldclient-rb/integrations/redis.rb +42 -2
  28. data/lib/ldclient-rb/integrations/test_data/flag_builder.rb +438 -0
  29. data/lib/ldclient-rb/integrations/test_data.rb +209 -0
  30. data/lib/ldclient-rb/integrations/util/store_wrapper.rb +5 -0
  31. data/lib/ldclient-rb/integrations.rb +2 -51
  32. data/lib/ldclient-rb/interfaces.rb +152 -2
  33. data/lib/ldclient-rb/ldclient.rb +131 -33
  34. data/lib/ldclient-rb/polling.rb +22 -41
  35. data/lib/ldclient-rb/requestor.rb +3 -3
  36. data/lib/ldclient-rb/stream.rb +4 -3
  37. data/lib/ldclient-rb/util.rb +10 -1
  38. data/lib/ldclient-rb/version.rb +1 -1
  39. data/lib/ldclient-rb.rb +0 -1
  40. metadata +35 -132
  41. data/.circleci/config.yml +0 -40
  42. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -37
  43. data/.github/ISSUE_TEMPLATE/config.yml +0 -5
  44. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  45. data/.github/pull_request_template.md +0 -21
  46. data/.gitignore +0 -16
  47. data/.hound.yml +0 -2
  48. data/.ldrelease/build-docs.sh +0 -18
  49. data/.ldrelease/circleci/linux/execute.sh +0 -18
  50. data/.ldrelease/circleci/mac/execute.sh +0 -18
  51. data/.ldrelease/circleci/template/build.sh +0 -29
  52. data/.ldrelease/circleci/template/publish.sh +0 -23
  53. data/.ldrelease/circleci/template/set-gem-home.sh +0 -7
  54. data/.ldrelease/circleci/template/test.sh +0 -10
  55. data/.ldrelease/circleci/template/update-version.sh +0 -8
  56. data/.ldrelease/circleci/windows/execute.ps1 +0 -19
  57. data/.ldrelease/config.yml +0 -29
  58. data/.rspec +0 -2
  59. data/.rubocop.yml +0 -600
  60. data/.simplecov +0 -4
  61. data/CHANGELOG.md +0 -351
  62. data/CODEOWNERS +0 -1
  63. data/CONTRIBUTING.md +0 -37
  64. data/Gemfile +0 -3
  65. data/azure-pipelines.yml +0 -51
  66. data/docs/Makefile +0 -26
  67. data/docs/index.md +0 -9
  68. data/launchdarkly-server-sdk.gemspec +0 -45
  69. data/lib/ldclient-rb/event_summarizer.rb +0 -55
  70. data/lib/ldclient-rb/impl/event_factory.rb +0 -120
  71. data/spec/config_spec.rb +0 -63
  72. data/spec/diagnostic_events_spec.rb +0 -163
  73. data/spec/evaluation_detail_spec.rb +0 -135
  74. data/spec/event_sender_spec.rb +0 -197
  75. data/spec/event_summarizer_spec.rb +0 -63
  76. data/spec/events_spec.rb +0 -607
  77. data/spec/expiring_cache_spec.rb +0 -76
  78. data/spec/feature_store_spec_base.rb +0 -213
  79. data/spec/file_data_source_spec.rb +0 -283
  80. data/spec/fixtures/feature.json +0 -37
  81. data/spec/fixtures/feature1.json +0 -36
  82. data/spec/fixtures/user.json +0 -9
  83. data/spec/flags_state_spec.rb +0 -81
  84. data/spec/http_util.rb +0 -132
  85. data/spec/impl/evaluator_bucketing_spec.rb +0 -111
  86. data/spec/impl/evaluator_clause_spec.rb +0 -55
  87. data/spec/impl/evaluator_operators_spec.rb +0 -141
  88. data/spec/impl/evaluator_rule_spec.rb +0 -96
  89. data/spec/impl/evaluator_segment_spec.rb +0 -125
  90. data/spec/impl/evaluator_spec.rb +0 -305
  91. data/spec/impl/evaluator_spec_base.rb +0 -75
  92. data/spec/impl/model/serialization_spec.rb +0 -41
  93. data/spec/in_memory_feature_store_spec.rb +0 -12
  94. data/spec/integrations/consul_feature_store_spec.rb +0 -40
  95. data/spec/integrations/dynamodb_feature_store_spec.rb +0 -103
  96. data/spec/integrations/store_wrapper_spec.rb +0 -276
  97. data/spec/launchdarkly-server-sdk_spec.rb +0 -13
  98. data/spec/launchdarkly-server-sdk_spec_autoloadtest.rb +0 -9
  99. data/spec/ldclient_end_to_end_spec.rb +0 -157
  100. data/spec/ldclient_spec.rb +0 -643
  101. data/spec/newrelic_spec.rb +0 -5
  102. data/spec/polling_spec.rb +0 -120
  103. data/spec/redis_feature_store_spec.rb +0 -121
  104. data/spec/requestor_spec.rb +0 -196
  105. data/spec/segment_store_spec_base.rb +0 -95
  106. data/spec/simple_lru_cache_spec.rb +0 -24
  107. data/spec/spec_helper.rb +0 -9
  108. data/spec/store_spec.rb +0 -10
  109. data/spec/stream_spec.rb +0 -45
  110. data/spec/user_filter_spec.rb +0 -91
  111. data/spec/util_spec.rb +0 -17
  112. data/spec/version_spec.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 631066b2968b323ed2e12aed1565c76cf1f8bb6284e8372121771577b49bda18
4
- data.tar.gz: 3e6b7c3b9769c917996e844c598796912f19c20e796692b877a885886d8fa070
3
+ metadata.gz: 147fe8142bffa0d8e754e86669f524f6d787930e8bc6b8a14d30429933a036e3
4
+ data.tar.gz: e4a404cb7bc911f7c156c3fe5059ee9a4a9d7ebfeacba4c52f44ceb116276835
5
5
  SHA512:
6
- metadata.gz: 5a885a5714a9cc157e295dd1a88a353a546847a702a771b4edf49f33c081eb19c4141ee7a0b4a8004620c1a4c20ef0111af0c0900ee3a28845f29e2385ebd13c
7
- data.tar.gz: 6e604eac4e997431d09257bf97ec115f3a130293e4bc83fa08254baaa921eb28a2230e5bc2bd080c855293e773331e5eed006741db6cd9943132a1f2a1dc243d
6
+ metadata.gz: '039348a1a0c9284e79e641b69f11bdc4e8ba57c4cad3320eea6f8bb8caf8fc0f52a02c427a2b4f26584945e5750b7728706855cfaf6bdc22a1863b55bcf934a6'
7
+ data.tar.gz: 452c574e6ff6323a74dfdcf6a5c936ff38bfaa0efc3b58ff190068322ea82e25b15dc20868eb22bf93361d3daa699bd51fa362e97f30f4fc6bcf402f9f5597d9
data/README.md CHANGED
@@ -3,14 +3,13 @@ LaunchDarkly Server-side SDK for Ruby
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/launchdarkly-server-sdk.svg)](http://badge.fury.io/rb/launchdarkly-server-sdk)
5
5
 
6
- [![Circle CI](https://circleci.com/gh/launchdarkly/ruby-server-sdk/tree/master.svg?style=svg)](https://circleci.com/gh/launchdarkly/ruby-server-sdk/tree/master)
7
- [![Security](https://hakiri.io/github/launchdarkly/ruby-server-sdk/master.svg)](https://hakiri.io/github/launchdarkly/ruby-server-sdk/master)
6
+ [![Circle CI](https://circleci.com/gh/launchdarkly/ruby-server-sdk/tree/main.svg?style=svg)](https://circleci.com/gh/launchdarkly/ruby-server-sdk/tree/main)
8
7
  [![RubyDoc](https://img.shields.io/static/v1?label=docs+-+all+versions&message=reference&color=00add8)](https://www.rubydoc.info/gems/launchdarkly-server-sdk)
9
8
  [![GitHub Pages](https://img.shields.io/static/v1?label=docs+-+latest&message=reference&color=00add8)](https://launchdarkly.github.io/ruby-server-sdk)
10
9
 
11
10
  LaunchDarkly overview
12
11
  -------------------------
13
- [LaunchDarkly](https://www.launchdarkly.com) is a feature management platform that serves over 100 billion feature flags daily to help teams build better software, faster. [Get started](https://docs.launchdarkly.com/docs/getting-started) using LaunchDarkly today!
12
+ [LaunchDarkly](https://www.launchdarkly.com) is a feature management platform that serves over 100 billion feature flags daily to help teams build better software, faster. [Get started](https://docs.launchdarkly.com/home/getting-started) using LaunchDarkly today!
14
13
 
15
14
  [![Twitter Follow](https://img.shields.io/twitter/follow/launchdarkly.svg?style=social&label=Follow&maxAge=2592000)](https://twitter.com/intent/follow?screen_name=launchdarkly)
16
15
 
@@ -22,7 +21,7 @@ This version of the LaunchDarkly SDK has a minimum Ruby version of 2.5.0, or 9.2
22
21
  Getting started
23
22
  -----------
24
23
 
25
- Refer to the [SDK documentation](https://docs.launchdarkly.com/docs/ruby-sdk-reference#section-getting-started) for instructions on getting started with using the SDK.
24
+ Refer to the [SDK documentation](https://docs.launchdarkly.com/sdk/server-side/ruby#getting-started) for instructions on getting started with using the SDK.
26
25
 
27
26
  Learn more
28
27
  -----------
@@ -49,7 +48,7 @@ About LaunchDarkly
49
48
  * Gradually roll out a feature to an increasing percentage of users, and track the effect that the feature has on key metrics (for instance, how likely is a user to complete a purchase if they have feature A versus feature B?).
50
49
  * Turn off a feature that you realize is causing performance problems in production, without needing to re-deploy, or even restart the application with a changed configuration file.
51
50
  * Grant access to certain features based on user attributes, like payment plan (eg: users on the ‘gold’ plan get access to more features than users in the ‘silver’ plan). Disable parts of your application to facilitate maintenance, without taking everything offline.
52
- * LaunchDarkly provides feature flag SDKs for a wide variety of languages and technologies. Check out [our documentation](https://docs.launchdarkly.com/docs) for a complete list.
51
+ * LaunchDarkly provides feature flag SDKs for a wide variety of languages and technologies. Read [our documentation](https://docs.launchdarkly.com/sdk) for a complete list.
53
52
  * Explore LaunchDarkly
54
53
  * [launchdarkly.com](https://www.launchdarkly.com/ "LaunchDarkly Main Website") for more information
55
54
  * [docs.launchdarkly.com](https://docs.launchdarkly.com/ "LaunchDarkly Documentation") for our documentation and SDK reference guides
@@ -21,6 +21,7 @@ module LaunchDarkly
21
21
  # @option opts [Integer] :capacity (10000) See {#capacity}.
22
22
  # @option opts [Float] :flush_interval (30) See {#flush_interval}.
23
23
  # @option opts [Float] :read_timeout (10) See {#read_timeout}.
24
+ # @option opts [Float] :initial_reconnect_delay (1) See {#initial_reconnect_delay}.
24
25
  # @option opts [Float] :connect_timeout (2) See {#connect_timeout}.
25
26
  # @option opts [Object] :cache_store See {#cache_store}.
26
27
  # @option opts [Object] :feature_store See {#feature_store}.
@@ -42,6 +43,8 @@ module LaunchDarkly
42
43
  # @option opts [String] :wrapper_name See {#wrapper_name}.
43
44
  # @option opts [String] :wrapper_version See {#wrapper_version}.
44
45
  # @option opts [#open] :socket_factory See {#socket_factory}.
46
+ # @option opts [BigSegmentsConfig] :big_segments See {#big_segments}.
47
+ # @option opts [Hash] :application See {#application}
45
48
  #
46
49
  def initialize(opts = {})
47
50
  @base_uri = (opts[:base_uri] || Config.default_base_uri).chomp("/")
@@ -53,6 +56,7 @@ module LaunchDarkly
53
56
  @flush_interval = opts[:flush_interval] || Config.default_flush_interval
54
57
  @connect_timeout = opts[:connect_timeout] || Config.default_connect_timeout
55
58
  @read_timeout = opts[:read_timeout] || Config.default_read_timeout
59
+ @initial_reconnect_delay = opts[:initial_reconnect_delay] || Config.default_initial_reconnect_delay
56
60
  @feature_store = opts[:feature_store] || Config.default_feature_store
57
61
  @stream = opts.has_key?(:stream) ? opts[:stream] : Config.default_stream
58
62
  @use_ldd = opts.has_key?(:use_ldd) ? opts[:use_ldd] : Config.default_use_ldd
@@ -73,6 +77,8 @@ module LaunchDarkly
73
77
  @wrapper_name = opts[:wrapper_name]
74
78
  @wrapper_version = opts[:wrapper_version]
75
79
  @socket_factory = opts[:socket_factory]
80
+ @big_segments = opts[:big_segments] || BigSegmentsConfig.new(store: nil)
81
+ @application = LaunchDarkly::Impl::Util.validate_application_info(opts[:application] || {}, @logger)
76
82
  end
77
83
 
78
84
  #
@@ -110,8 +116,8 @@ module LaunchDarkly
110
116
  # Whether to use the LaunchDarkly relay proxy in daemon mode. In this mode, the client does not
111
117
  # use polling or streaming to get feature flag updates from the server, but instead reads them
112
118
  # from the {#feature_store feature store}, which is assumed to be a database that is populated by
113
- # a LaunchDarkly relay proxy. For more information, see ["The relay proxy"](https://docs.launchdarkly.com/v2.0/docs/the-relay-proxy)
114
- # and ["Using a persistent feature store"](https://docs.launchdarkly.com/v2.0/docs/using-a-persistent-feature-store).
119
+ # a LaunchDarkly relay proxy. For more information, see ["The relay proxy"](https://docs.launchdarkly.com/home/relay-proxy)
120
+ # and ["Using a persistent data stores"](https://docs.launchdarkly.com/sdk/concepts/data-stores).
115
121
  #
116
122
  # All other properties related to streaming or polling are ignored if this option is set to true.
117
123
  #
@@ -178,6 +184,13 @@ module LaunchDarkly
178
184
  #
179
185
  attr_reader :read_timeout
180
186
 
187
+ #
188
+ # The initial delay before reconnecting after an error in the SSE client.
189
+ # This only applies to the streaming connection.
190
+ # @return [Float]
191
+ #
192
+ attr_reader :initial_reconnect_delay
193
+
181
194
  #
182
195
  # The connect timeout for network connections in seconds.
183
196
  # @return [Float]
@@ -189,7 +202,7 @@ module LaunchDarkly
189
202
  # from LaunchDarkly, and uses the last stored data when evaluating flags. Defaults to
190
203
  # {InMemoryFeatureStore}; for other implementations, see {LaunchDarkly::Integrations}.
191
204
  #
192
- # For more information, see ["Using a persistent feature store"](https://docs.launchdarkly.com/v2.0/docs/using-a-persistent-feature-store).
205
+ # For more information, see ["Persistent data stores"](https://docs.launchdarkly.com/sdk/concepts/data-stores).
193
206
  #
194
207
  # @return [LaunchDarkly::Interfaces::FeatureStore]
195
208
  #
@@ -258,10 +271,39 @@ module LaunchDarkly
258
271
  # object.
259
272
  #
260
273
  # @return [LaunchDarkly::Interfaces::DataSource|lambda]
261
- # @see FileDataSource
274
+ # @see LaunchDarkly::Integrations::FileData
275
+ # @see LaunchDarkly::Integrations::TestData
262
276
  #
263
277
  attr_reader :data_source
264
278
 
279
+ #
280
+ # Configuration options related to Big Segments.
281
+ #
282
+ # Big Segments are a specific type of user segments. For more information, read the LaunchDarkly
283
+ # documentation: https://docs.launchdarkly.com/home/users/big-segments
284
+ #
285
+ # @return [BigSegmentsConfig]
286
+ #
287
+ attr_reader :big_segments
288
+
289
+ #
290
+ # An object that allows configuration of application metadata.
291
+ #
292
+ # Application metadata may be used in LaunchDarkly analytics or other product features, but does not affect feature flag evaluations.
293
+ #
294
+ # If you want to set non-default values for any of these fields, provide the appropriately configured hash to the {Config} object.
295
+ #
296
+ # @example Configuring application information
297
+ # opts[:application] = {
298
+ # id: "MY APPLICATION ID",
299
+ # version: "MY APPLICATION VERSION"
300
+ # }
301
+ # config = LDConfig.new(opts)
302
+ #
303
+ # @return [Hash]
304
+ #
305
+ attr_reader :application
306
+
265
307
  # @deprecated This is replaced by {#data_source}.
266
308
  attr_reader :update_processor
267
309
 
@@ -382,6 +424,14 @@ module LaunchDarkly
382
424
  10
383
425
  end
384
426
 
427
+ #
428
+ # The default value for {#initial_reconnect_delay}.
429
+ # @return [Float] 1
430
+ #
431
+ def self.default_initial_reconnect_delay
432
+ 1
433
+ end
434
+
385
435
  #
386
436
  # The default value for {#connect_timeout}.
387
437
  # @return [Float] 10
@@ -484,4 +534,68 @@ module LaunchDarkly
484
534
  60
485
535
  end
486
536
  end
537
+
538
+ #
539
+ # Configuration options related to Big Segments.
540
+ #
541
+ # Big Segments are a specific type of user segments. For more information, read the LaunchDarkly
542
+ # documentation: https://docs.launchdarkly.com/home/users/big-segments
543
+ #
544
+ # If your application uses Big Segments, you will need to create a `BigSegmentsConfig` that at a
545
+ # minimum specifies what database integration to use, and then pass the `BigSegmentsConfig`
546
+ # object as the `big_segments` parameter when creating a {Config}.
547
+ #
548
+ # @example Configuring Big Segments with Redis
549
+ # store = LaunchDarkly::Integrations::Redis::new_big_segments_store(redis_url: "redis://my-server")
550
+ # config = LaunchDarkly::Config.new(big_segments:
551
+ # LaunchDarkly::BigSegmentsConfig.new(store: store))
552
+ # client = LaunchDarkly::LDClient.new(my_sdk_key, config)
553
+ #
554
+ class BigSegmentsConfig
555
+ DEFAULT_USER_CACHE_SIZE = 1000
556
+ DEFAULT_USER_CACHE_TIME = 5
557
+ DEFAULT_STATUS_POLL_INTERVAL = 5
558
+ DEFAULT_STALE_AFTER = 2 * 60
559
+
560
+ #
561
+ # Constructor for setting Big Segments options.
562
+ #
563
+ # @param store [LaunchDarkly::Interfaces::BigSegmentStore] the data store implementation
564
+ # @param user_cache_size [Integer] See {#user_cache_size}.
565
+ # @param user_cache_time [Float] See {#user_cache_time}.
566
+ # @param status_poll_interval [Float] See {#status_poll_interval}.
567
+ # @param stale_after [Float] See {#stale_after}.
568
+ #
569
+ def initialize(store:, user_cache_size: nil, user_cache_time: nil, status_poll_interval: nil, stale_after: nil)
570
+ @store = store
571
+ @user_cache_size = user_cache_size.nil? ? DEFAULT_USER_CACHE_SIZE : user_cache_size
572
+ @user_cache_time = user_cache_time.nil? ? DEFAULT_USER_CACHE_TIME : user_cache_time
573
+ @status_poll_interval = status_poll_interval.nil? ? DEFAULT_STATUS_POLL_INTERVAL : status_poll_interval
574
+ @stale_after = stale_after.nil? ? DEFAULT_STALE_AFTER : stale_after
575
+ end
576
+
577
+ # The implementation of {LaunchDarkly::Interfaces::BigSegmentStore} that will be used to
578
+ # query the Big Segments database.
579
+ # @return [LaunchDarkly::Interfaces::BigSegmentStore]
580
+ attr_reader :store
581
+
582
+ # The maximum number of users whose Big Segment state will be cached by the SDK at any given time.
583
+ # @return [Integer]
584
+ attr_reader :user_cache_size
585
+
586
+ # The maximum length of time (in seconds) that the Big Segment state for a user will be cached
587
+ # by the SDK.
588
+ # @return [Float]
589
+ attr_reader :user_cache_time
590
+
591
+ # The interval (in seconds) at which the SDK will poll the Big Segment store to make sure it is
592
+ # available and to determine how long ago it was updated.
593
+ # @return [Float]
594
+ attr_reader :status_poll_interval
595
+
596
+ # The maximum length of time between updates of the Big Segments data before the data is
597
+ # considered out of date.
598
+ # @return [Float]
599
+ attr_reader :stale_after
600
+ end
487
601
  end
@@ -110,24 +110,42 @@ module LaunchDarkly
110
110
 
111
111
  # Indicates the general category of the reason. Will always be one of the class constants such
112
112
  # as {#OFF}.
113
+ # @return [Symbol]
113
114
  attr_reader :kind
114
115
 
115
116
  # The index of the rule that was matched (0 for the first rule in the feature flag). If
116
117
  # {#kind} is not {#RULE_MATCH}, this will be `nil`.
118
+ # @return [Integer|nil]
117
119
  attr_reader :rule_index
118
120
 
119
121
  # A unique string identifier for the matched rule, which will not change if other rules are added
120
122
  # or deleted. If {#kind} is not {#RULE_MATCH}, this will be `nil`.
123
+ # @return [String]
121
124
  attr_reader :rule_id
122
125
 
126
+ # A boolean or nil value representing if the rule or fallthrough has an experiment rollout.
127
+ # @return [Boolean|nil]
128
+ attr_reader :in_experiment
129
+
123
130
  # The key of the prerequisite flag that did not return the desired variation. If {#kind} is not
124
131
  # {#PREREQUISITE_FAILED}, this will be `nil`.
132
+ # @return [String]
125
133
  attr_reader :prerequisite_key
126
134
 
127
135
  # A value indicating the general category of error. This should be one of the class constants such
128
136
  # as {#ERROR_FLAG_NOT_FOUND}. If {#kind} is not {#ERROR}, it will be `nil`.
137
+ # @return [Symbol]
129
138
  attr_reader :error_kind
130
139
 
140
+ # Describes the validity of Big Segment information, if and only if the flag evaluation required
141
+ # querying at least one Big Segment. Otherwise it returns `nil`. Possible values are defined by
142
+ # {BigSegmentsStatus}.
143
+ #
144
+ # Big Segments are a specific kind of user segments. For more information, read the LaunchDarkly
145
+ # documentation: https://docs.launchdarkly.com/home/users/big-segments
146
+ # @return [Symbol]
147
+ attr_reader :big_segments_status
148
+
131
149
  # Returns an instance whose {#kind} is {#OFF}.
132
150
  # @return [EvaluationReason]
133
151
  def self.off
@@ -136,8 +154,12 @@ module LaunchDarkly
136
154
 
137
155
  # Returns an instance whose {#kind} is {#FALLTHROUGH}.
138
156
  # @return [EvaluationReason]
139
- def self.fallthrough
140
- @@fallthrough
157
+ def self.fallthrough(in_experiment=false)
158
+ if in_experiment
159
+ @@fallthrough_with_experiment
160
+ else
161
+ @@fallthrough
162
+ end
141
163
  end
142
164
 
143
165
  # Returns an instance whose {#kind} is {#TARGET_MATCH}.
@@ -153,10 +175,16 @@ module LaunchDarkly
153
175
  # @param rule_id [String] unique string identifier for the matched rule
154
176
  # @return [EvaluationReason]
155
177
  # @raise [ArgumentError] if `rule_index` is not a number or `rule_id` is not a string
156
- def self.rule_match(rule_index, rule_id)
178
+ def self.rule_match(rule_index, rule_id, in_experiment=false)
157
179
  raise ArgumentError.new("rule_index must be a number") if !(rule_index.is_a? Numeric)
158
180
  raise ArgumentError.new("rule_id must be a string") if !rule_id.nil? && !(rule_id.is_a? String) # in test data, ID could be nil
159
- new(:RULE_MATCH, rule_index, rule_id, nil, nil)
181
+
182
+ if in_experiment
183
+ er = new(:RULE_MATCH, rule_index, rule_id, nil, nil, true)
184
+ else
185
+ er = new(:RULE_MATCH, rule_index, rule_id, nil, nil)
186
+ end
187
+ er
160
188
  end
161
189
 
162
190
  # Returns an instance whose {#kind} is {#PREREQUISITE_FAILED}.
@@ -183,11 +211,13 @@ module LaunchDarkly
183
211
  def ==(other)
184
212
  if other.is_a? EvaluationReason
185
213
  @kind == other.kind && @rule_index == other.rule_index && @rule_id == other.rule_id &&
186
- @prerequisite_key == other.prerequisite_key && @error_kind == other.error_kind
214
+ @prerequisite_key == other.prerequisite_key && @error_kind == other.error_kind &&
215
+ @big_segments_status == other.big_segments_status
187
216
  elsif other.is_a? Hash
188
217
  @kind.to_s == other[:kind] && @rule_index == other[:ruleIndex] && @rule_id == other[:ruleId] &&
189
218
  @prerequisite_key == other[:prerequisiteKey] &&
190
- (other[:errorKind] == @error_kind.nil? ? nil : @error_kind.to_s)
219
+ (other[:errorKind] == @error_kind.nil? ? nil : @error_kind.to_s) &&
220
+ (other[:bigSegmentsStatus] == @big_segments_status.nil? ? nil : @big_segments_status.to_s)
191
221
  end
192
222
  end
193
223
 
@@ -204,11 +234,17 @@ module LaunchDarkly
204
234
  def inspect
205
235
  case @kind
206
236
  when :RULE_MATCH
207
- "RULE_MATCH(#{@rule_index},#{@rule_id})"
237
+ if @in_experiment
238
+ "RULE_MATCH(#{@rule_index},#{@rule_id},#{@in_experiment})"
239
+ else
240
+ "RULE_MATCH(#{@rule_index},#{@rule_id})"
241
+ end
208
242
  when :PREREQUISITE_FAILED
209
243
  "PREREQUISITE_FAILED(#{@prerequisite_key})"
210
244
  when :ERROR
211
245
  "ERROR(#{@error_kind})"
246
+ when :FALLTHROUGH
247
+ @in_experiment ? "FALLTHROUGH(#{@in_experiment})" : @kind.to_s
212
248
  else
213
249
  @kind.to_s
214
250
  end
@@ -223,16 +259,30 @@ module LaunchDarkly
223
259
  # enabled for a flag and the application called variation_detail, or 2. experimentation is
224
260
  # enabled for an evaluation. We can't reuse these hashes because an application could call
225
261
  # as_json and then modify the result.
226
- case @kind
262
+ ret = case @kind
227
263
  when :RULE_MATCH
228
- { kind: @kind, ruleIndex: @rule_index, ruleId: @rule_id }
264
+ if @in_experiment
265
+ { kind: @kind, ruleIndex: @rule_index, ruleId: @rule_id, inExperiment: @in_experiment }
266
+ else
267
+ { kind: @kind, ruleIndex: @rule_index, ruleId: @rule_id }
268
+ end
229
269
  when :PREREQUISITE_FAILED
230
270
  { kind: @kind, prerequisiteKey: @prerequisite_key }
231
271
  when :ERROR
232
272
  { kind: @kind, errorKind: @error_kind }
273
+ when :FALLTHROUGH
274
+ if @in_experiment
275
+ { kind: @kind, inExperiment: @in_experiment }
276
+ else
277
+ { kind: @kind }
278
+ end
233
279
  else
234
280
  { kind: @kind }
235
281
  end
282
+ if !@big_segments_status.nil?
283
+ ret[:bigSegmentsStatus] = @big_segments_status
284
+ end
285
+ ret
236
286
  end
237
287
 
238
288
  # Same as {#as_json}, but converts the JSON structure into a string.
@@ -256,14 +306,24 @@ module LaunchDarkly
256
306
  @prerequisite_key
257
307
  when :errorKind
258
308
  @error_kind.nil? ? nil : @error_kind.to_s
309
+ when :bigSegmentsStatus
310
+ @big_segments_status.nil? ? nil : @big_segments_status.to_s
259
311
  else
260
312
  nil
261
313
  end
262
314
  end
263
315
 
264
- private
316
+ def with_big_segments_status(big_segments_status)
317
+ return self if @big_segments_status == big_segments_status
318
+ EvaluationReason.new(@kind, @rule_index, @rule_id, @prerequisite_key, @error_kind, @in_experiment, big_segments_status)
319
+ end
265
320
 
266
- def initialize(kind, rule_index, rule_id, prerequisite_key, error_kind)
321
+ #
322
+ # Constructor that sets all properties. Applications should not normally use this constructor,
323
+ # but should use class methods like {#off} to avoid creating unnecessary instances.
324
+ #
325
+ def initialize(kind, rule_index, rule_id, prerequisite_key, error_kind, in_experiment=nil,
326
+ big_segments_status = nil)
267
327
  @kind = kind.to_sym
268
328
  @rule_index = rule_index
269
329
  @rule_id = rule_id
@@ -271,14 +331,15 @@ module LaunchDarkly
271
331
  @prerequisite_key = prerequisite_key
272
332
  @prerequisite_key.freeze if !prerequisite_key.nil?
273
333
  @error_kind = error_kind
334
+ @in_experiment = in_experiment
335
+ @big_segments_status = big_segments_status
274
336
  end
275
337
 
276
- private_class_method :new
277
-
278
- def self.make_error(error_kind)
338
+ private_class_method def self.make_error(error_kind)
279
339
  new(:ERROR, nil, nil, nil, error_kind)
280
340
  end
281
341
 
342
+ @@fallthrough_with_experiment = new(:FALLTHROUGH, nil, nil, nil, nil, true)
282
343
  @@fallthrough = new(:FALLTHROUGH, nil, nil, nil, nil)
283
344
  @@off = new(:OFF, nil, nil, nil, nil)
284
345
  @@target_match = new(:TARGET_MATCH, nil, nil, nil, nil)
@@ -290,4 +351,33 @@ module LaunchDarkly
290
351
  ERROR_EXCEPTION => make_error(ERROR_EXCEPTION)
291
352
  }
292
353
  end
354
+
355
+ #
356
+ # Defines the possible values of {EvaluationReason#big_segments_status}.
357
+ #
358
+ module BigSegmentsStatus
359
+ #
360
+ # Indicates that the Big Segment query involved in the flag evaluation was successful, and
361
+ # that the segment state is considered up to date.
362
+ #
363
+ HEALTHY = :HEALTHY
364
+
365
+ #
366
+ # Indicates that the Big Segment query involved in the flag evaluation was successful, but
367
+ # that the segment state may not be up to date.
368
+ #
369
+ STALE = :STALE
370
+
371
+ #
372
+ # Indicates that Big Segments could not be queried for the flag evaluation because the SDK
373
+ # configuration did not include a Big Segment store.
374
+ #
375
+ NOT_CONFIGURED = :NOT_CONFIGURED
376
+
377
+ #
378
+ # Indicates that the Big Segment query involved in the flag evaluation failed, for instance
379
+ # due to a database error.
380
+ #
381
+ STORE_ERROR = :STORE_ERROR
382
+ end
293
383
  end