launchdarkly-server-sdk 6.3.0 → 8.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -4
  3. data/lib/ldclient-rb/config.rb +112 -62
  4. data/lib/ldclient-rb/context.rb +444 -0
  5. data/lib/ldclient-rb/evaluation_detail.rb +26 -22
  6. data/lib/ldclient-rb/events.rb +256 -146
  7. data/lib/ldclient-rb/flags_state.rb +26 -15
  8. data/lib/ldclient-rb/impl/big_segments.rb +18 -18
  9. data/lib/ldclient-rb/impl/broadcaster.rb +78 -0
  10. data/lib/ldclient-rb/impl/context.rb +96 -0
  11. data/lib/ldclient-rb/impl/context_filter.rb +145 -0
  12. data/lib/ldclient-rb/impl/data_source.rb +188 -0
  13. data/lib/ldclient-rb/impl/data_store.rb +59 -0
  14. data/lib/ldclient-rb/impl/dependency_tracker.rb +102 -0
  15. data/lib/ldclient-rb/impl/diagnostic_events.rb +9 -10
  16. data/lib/ldclient-rb/impl/evaluator.rb +386 -142
  17. data/lib/ldclient-rb/impl/evaluator_bucketing.rb +40 -41
  18. data/lib/ldclient-rb/impl/evaluator_helpers.rb +50 -0
  19. data/lib/ldclient-rb/impl/evaluator_operators.rb +26 -55
  20. data/lib/ldclient-rb/impl/event_sender.rb +7 -6
  21. data/lib/ldclient-rb/impl/event_summarizer.rb +68 -0
  22. data/lib/ldclient-rb/impl/event_types.rb +136 -0
  23. data/lib/ldclient-rb/impl/flag_tracker.rb +58 -0
  24. data/lib/ldclient-rb/impl/integrations/consul_impl.rb +19 -7
  25. data/lib/ldclient-rb/impl/integrations/dynamodb_impl.rb +38 -30
  26. data/lib/ldclient-rb/impl/integrations/file_data_source.rb +24 -11
  27. data/lib/ldclient-rb/impl/integrations/redis_impl.rb +109 -12
  28. data/lib/ldclient-rb/impl/migrations/migrator.rb +287 -0
  29. data/lib/ldclient-rb/impl/migrations/tracker.rb +136 -0
  30. data/lib/ldclient-rb/impl/model/clause.rb +45 -0
  31. data/lib/ldclient-rb/impl/model/feature_flag.rb +255 -0
  32. data/lib/ldclient-rb/impl/model/preprocessed_data.rb +64 -0
  33. data/lib/ldclient-rb/impl/model/segment.rb +132 -0
  34. data/lib/ldclient-rb/impl/model/serialization.rb +54 -44
  35. data/lib/ldclient-rb/impl/repeating_task.rb +3 -4
  36. data/lib/ldclient-rb/impl/sampler.rb +25 -0
  37. data/lib/ldclient-rb/impl/store_client_wrapper.rb +102 -8
  38. data/lib/ldclient-rb/impl/store_data_set_sorter.rb +2 -2
  39. data/lib/ldclient-rb/impl/unbounded_pool.rb +1 -1
  40. data/lib/ldclient-rb/impl/util.rb +59 -1
  41. data/lib/ldclient-rb/in_memory_store.rb +9 -2
  42. data/lib/ldclient-rb/integrations/consul.rb +2 -2
  43. data/lib/ldclient-rb/integrations/dynamodb.rb +2 -2
  44. data/lib/ldclient-rb/integrations/file_data.rb +4 -4
  45. data/lib/ldclient-rb/integrations/redis.rb +5 -5
  46. data/lib/ldclient-rb/integrations/test_data/flag_builder.rb +287 -62
  47. data/lib/ldclient-rb/integrations/test_data.rb +18 -14
  48. data/lib/ldclient-rb/integrations/util/store_wrapper.rb +20 -9
  49. data/lib/ldclient-rb/interfaces.rb +600 -14
  50. data/lib/ldclient-rb/ldclient.rb +314 -134
  51. data/lib/ldclient-rb/memoized_value.rb +1 -1
  52. data/lib/ldclient-rb/migrations.rb +230 -0
  53. data/lib/ldclient-rb/non_blocking_thread_pool.rb +1 -1
  54. data/lib/ldclient-rb/polling.rb +52 -6
  55. data/lib/ldclient-rb/reference.rb +274 -0
  56. data/lib/ldclient-rb/requestor.rb +9 -11
  57. data/lib/ldclient-rb/stream.rb +96 -34
  58. data/lib/ldclient-rb/util.rb +97 -14
  59. data/lib/ldclient-rb/version.rb +1 -1
  60. data/lib/ldclient-rb.rb +3 -4
  61. metadata +65 -23
  62. data/lib/ldclient-rb/event_summarizer.rb +0 -55
  63. data/lib/ldclient-rb/file_data_source.rb +0 -23
  64. data/lib/ldclient-rb/impl/event_factory.rb +0 -126
  65. data/lib/ldclient-rb/newrelic.rb +0 -17
  66. data/lib/ldclient-rb/redis_store.rb +0 -88
  67. data/lib/ldclient-rb/user_filter.rb +0 -52
@@ -17,7 +17,7 @@ module LaunchDarkly
17
17
  # @private
18
18
  KEY_PATHS = {
19
19
  FEATURES => "/flags/",
20
- SEGMENTS => "/segments/"
20
+ SEGMENTS => "/segments/",
21
21
  }
22
22
 
23
23
  # @private
@@ -25,6 +25,7 @@ module LaunchDarkly
25
25
  def initialize(sdk_key, config, diagnostic_accumulator = nil)
26
26
  @sdk_key = sdk_key
27
27
  @config = config
28
+ @data_source_update_sink = config.data_source_update_sink
28
29
  @feature_store = config.feature_store
29
30
  @initialized = Concurrent::AtomicBoolean.new(false)
30
31
  @started = Concurrent::AtomicBoolean.new(false)
@@ -41,77 +42,138 @@ module LaunchDarkly
41
42
  return @ready unless @started.make_true
42
43
 
43
44
  @config.logger.info { "[LDClient] Initializing stream connection" }
44
-
45
+
45
46
  headers = Impl::Util.default_http_headers(@sdk_key, @config)
46
47
  opts = {
47
48
  headers: headers,
48
49
  read_timeout: READ_TIMEOUT_SECONDS,
49
50
  logger: @config.logger,
50
- socket_factory: @config.socket_factory
51
+ socket_factory: @config.socket_factory,
52
+ reconnect_time: @config.initial_reconnect_delay,
51
53
  }
52
54
  log_connection_started
53
- @es = SSE::Client.new(@config.stream_uri + "/all", **opts) do |conn|
55
+
56
+ uri = Util.add_payload_filter_key(@config.stream_uri + "/all", @config)
57
+ @es = SSE::Client.new(uri, **opts) do |conn|
54
58
  conn.on_event { |event| process_message(event) }
55
59
  conn.on_error { |err|
56
60
  log_connection_result(false)
57
61
  case err
58
62
  when SSE::Errors::HTTPStatusError
59
63
  status = err.status
64
+ error_info = LaunchDarkly::Interfaces::DataSource::ErrorInfo.new(
65
+ LaunchDarkly::Interfaces::DataSource::ErrorInfo::ERROR_RESPONSE, status, nil, Time.now)
60
66
  message = Util.http_error_message(status, "streaming connection", "will retry")
61
67
  @config.logger.error { "[LDClient] #{message}" }
62
- if !Util.http_error_recoverable?(status)
68
+
69
+ if Util.http_error_recoverable?(status)
70
+ @data_source_update_sink&.update_status(
71
+ LaunchDarkly::Interfaces::DataSource::Status::INTERRUPTED,
72
+ error_info
73
+ )
74
+ else
63
75
  @ready.set # if client was waiting on us, make it stop waiting - has no effect if already set
64
- stop
76
+ stop_with_error_info error_info
65
77
  end
78
+ when SSE::Errors::HTTPContentTypeError, SSE::Errors::HTTPProxyError, SSE::Errors::ReadTimeoutError
79
+ @data_source_update_sink&.update_status(
80
+ LaunchDarkly::Interfaces::DataSource::Status::INTERRUPTED,
81
+ LaunchDarkly::Interfaces::DataSource::ErrorInfo.new(LaunchDarkly::Interfaces::DataSource::ErrorInfo::NETWORK_ERROR, 0, err.to_s, Time.now)
82
+ )
83
+
84
+ else
85
+ @data_source_update_sink&.update_status(
86
+ LaunchDarkly::Interfaces::DataSource::Status::INTERRUPTED,
87
+ LaunchDarkly::Interfaces::DataSource::ErrorInfo.new(LaunchDarkly::Interfaces::DataSource::ErrorInfo::UNKNOWN, 0, err.to_s, Time.now)
88
+ )
66
89
  end
67
90
  }
68
91
  end
69
-
92
+
70
93
  @ready
71
94
  end
72
95
 
73
96
  def stop
97
+ stop_with_error_info
98
+ end
99
+
100
+ private
101
+
102
+ #
103
+ # @param [LaunchDarkly::Interfaces::DataSource::ErrorInfo, nil] error_info
104
+ #
105
+ def stop_with_error_info(error_info = nil)
74
106
  if @stopped.make_true
75
107
  @es.close
108
+ @data_source_update_sink&.update_status(LaunchDarkly::Interfaces::DataSource::Status::OFF, error_info)
76
109
  @config.logger.info { "[LDClient] Stream connection stopped" }
77
110
  end
78
111
  end
79
112
 
80
- private
113
+ #
114
+ # The original implementation of this class relied on the feature store
115
+ # directly, which we are trying to move away from. Customers who might have
116
+ # instantiated this directly for some reason wouldn't know they have to set
117
+ # the config's sink manually, so we have to fall back to the store if the
118
+ # sink isn't present.
119
+ #
120
+ # The next major release should be able to simplify this structure and
121
+ # remove the need for fall back to the data store because the update sink
122
+ # should always be present.
123
+ #
124
+ def update_sink_or_data_store
125
+ @data_source_update_sink || @feature_store
126
+ end
81
127
 
82
128
  def process_message(message)
83
129
  log_connection_result(true)
84
130
  method = message.type
85
131
  @config.logger.debug { "[LDClient] Stream received #{method} message: #{message.data}" }
86
- if method == PUT
87
- message = JSON.parse(message.data, symbolize_names: true)
88
- all_data = Impl::Model.make_all_store_data(message[:data])
89
- @feature_store.init(all_data)
90
- @initialized.make_true
91
- @config.logger.info { "[LDClient] Stream initialized" }
92
- @ready.set
93
- elsif method == PATCH
94
- data = JSON.parse(message.data, symbolize_names: true)
95
- for kind in [FEATURES, SEGMENTS]
96
- key = key_for_path(kind, data[:path])
97
- if key
98
- data = data[:data]
99
- Impl::Model.postprocess_item_after_deserializing!(kind, data)
100
- @feature_store.upsert(kind, data)
101
- break
132
+
133
+ begin
134
+ if method == PUT
135
+ message = JSON.parse(message.data, symbolize_names: true)
136
+ all_data = Impl::Model.make_all_store_data(message[:data], @config.logger)
137
+ update_sink_or_data_store.init(all_data)
138
+ @initialized.make_true
139
+ @config.logger.info { "[LDClient] Stream initialized" }
140
+ @ready.set
141
+ elsif method == PATCH
142
+ data = JSON.parse(message.data, symbolize_names: true)
143
+ for kind in [FEATURES, SEGMENTS]
144
+ key = key_for_path(kind, data[:path])
145
+ if key
146
+ item = Impl::Model.deserialize(kind, data[:data], @config.logger)
147
+ update_sink_or_data_store.upsert(kind, item)
148
+ break
149
+ end
102
150
  end
103
- end
104
- elsif method == DELETE
105
- data = JSON.parse(message.data, symbolize_names: true)
106
- for kind in [FEATURES, SEGMENTS]
107
- key = key_for_path(kind, data[:path])
108
- if key
109
- @feature_store.delete(kind, key, data[:version])
110
- break
151
+ elsif method == DELETE
152
+ data = JSON.parse(message.data, symbolize_names: true)
153
+ for kind in [FEATURES, SEGMENTS]
154
+ key = key_for_path(kind, data[:path])
155
+ if key
156
+ update_sink_or_data_store.delete(kind, key, data[:version])
157
+ break
158
+ end
111
159
  end
160
+ else
161
+ @config.logger.warn { "[LDClient] Unknown message received: #{method}" }
112
162
  end
113
- else
114
- @config.logger.warn { "[LDClient] Unknown message received: #{method}" }
163
+
164
+ @data_source_update_sink&.update_status(LaunchDarkly::Interfaces::DataSource::Status::VALID, nil)
165
+ rescue JSON::ParserError => e
166
+ @config.logger.error { "[LDClient] JSON parsing failed for method #{method}. Ignoring event." }
167
+ error_info = LaunchDarkly::Interfaces::DataSource::ErrorInfo.new(
168
+ LaunchDarkly::Interfaces::DataSource::ErrorInfo::INVALID_DATA,
169
+ 0,
170
+ e.to_s,
171
+ Time.now
172
+ )
173
+ @data_source_update_sink&.update_status(LaunchDarkly::Interfaces::DataSource::Status::INTERRUPTED, error_info)
174
+
175
+ # Re-raise the exception so the SSE implementation can catch it and restart the stream.
176
+ raise
115
177
  end
116
178
  end
117
179
 
@@ -2,21 +2,95 @@ require "uri"
2
2
  require "http"
3
3
 
4
4
  module LaunchDarkly
5
+ #
6
+ # A Result is used to reflect the outcome of any operation.
7
+ #
8
+ # Results can either be considered a success or a failure.
9
+ #
10
+ # In the event of success, the Result will contain an option, nullable value to hold any success value back to the
11
+ # calling function.
12
+ #
13
+ # If the operation fails, the Result will contain an error describing the value.
14
+ #
15
+ class Result
16
+ #
17
+ # Create a successful result with the provided value.
18
+ #
19
+ # @param value [Object, nil]
20
+ # @return [Result]
21
+ #
22
+ def self.success(value)
23
+ Result.new(value)
24
+ end
25
+
26
+ #
27
+ # Create a failed result with the provided error description.
28
+ #
29
+ # @param error [String]
30
+ # @param exception [Exception, nil]
31
+ # @return [Result]
32
+ #
33
+ def self.fail(error, exception = nil)
34
+ Result.new(nil, error, exception)
35
+ end
36
+
37
+ #
38
+ # Was this result successful or did it encounter an error?
39
+ #
40
+ # @return [Boolean]
41
+ #
42
+ def success?
43
+ @error.nil?
44
+ end
45
+
46
+ #
47
+ # @return [Object, nil] The value returned from the operation if it was successful; nil otherwise.
48
+ #
49
+ attr_reader :value
50
+
51
+ #
52
+ # @return [String, nil] An error description of the failure; nil otherwise
53
+ #
54
+ attr_reader :error
55
+
56
+ #
57
+ # @return [Exception, nil] An optional exception which caused the failure
58
+ #
59
+ attr_reader :exception
60
+
61
+ private def initialize(value, error = nil, exception = nil)
62
+ @value = value
63
+ @error = error
64
+ @exception = exception
65
+ end
66
+ end
67
+
5
68
  # @private
6
69
  module Util
7
- def self.stringify_attrs(hash, attrs)
8
- return hash if hash.nil?
9
- ret = hash
10
- changed = false
11
- attrs.each do |attr|
12
- value = hash[attr]
13
- if !value.nil? && !value.is_a?(String)
14
- ret = hash.clone if !changed
15
- ret[attr] = value.to_s
16
- changed = true
17
- end
70
+ #
71
+ # Append the payload filter key query parameter to the provided URI.
72
+ #
73
+ # @param uri [String]
74
+ # @param config [Config]
75
+ # @return [String]
76
+ #
77
+ def self.add_payload_filter_key(uri, config)
78
+ return uri if config.payload_filter_key.nil?
79
+
80
+ unless config.payload_filter_key.is_a?(String) && !config.payload_filter_key.empty?
81
+ config.logger.warn { "[LDClient] Filter key must be a non-empty string. No filtering will be applied." }
82
+ return uri
83
+ end
84
+
85
+ begin
86
+ parsed = URI.parse(uri)
87
+ new_query_params = URI.decode_www_form(String(parsed.query)) << ["filter", config.payload_filter_key]
88
+ parsed.query = URI.encode_www_form(new_query_params)
89
+ parsed.to_s
90
+ rescue URI::InvalidURIError
91
+ config.logger.warn { "[LDClient] URI could not be parsed. No filtering will be applied." }
92
+ uri
18
93
  end
19
- ret
20
94
  end
21
95
 
22
96
  def self.new_http_client(uri_s, config)
@@ -24,10 +98,19 @@ module LaunchDarkly
24
98
  if config.socket_factory
25
99
  http_client_options["socket_class"] = config.socket_factory
26
100
  end
27
- return HTTP::Client.new(http_client_options)
101
+ proxy = URI.parse(uri_s).find_proxy
102
+ unless proxy.nil?
103
+ http_client_options["proxy"] = {
104
+ proxy_address: proxy.host,
105
+ proxy_port: proxy.port,
106
+ proxy_username: proxy.user,
107
+ proxy_password: proxy.password,
108
+ }
109
+ end
110
+ HTTP::Client.new(http_client_options)
28
111
  .timeout({
29
112
  read: config.read_timeout,
30
- connect: config.connect_timeout
113
+ connect: config.connect_timeout,
31
114
  })
32
115
  .persistent(uri_s)
33
116
  end
@@ -1,3 +1,3 @@
1
1
  module LaunchDarkly
2
- VERSION = "6.3.0"
2
+ VERSION = "8.0.0"
3
3
  end
data/lib/ldclient-rb.rb CHANGED
@@ -9,20 +9,19 @@ require "ldclient-rb/version"
9
9
  require "ldclient-rb/interfaces"
10
10
  require "ldclient-rb/util"
11
11
  require "ldclient-rb/flags_state"
12
+ require "ldclient-rb/migrations"
12
13
  require "ldclient-rb/ldclient"
13
14
  require "ldclient-rb/cache_store"
14
15
  require "ldclient-rb/expiring_cache"
15
16
  require "ldclient-rb/memoized_value"
16
17
  require "ldclient-rb/in_memory_store"
17
18
  require "ldclient-rb/config"
18
- require "ldclient-rb/newrelic"
19
+ require "ldclient-rb/context"
20
+ require "ldclient-rb/reference"
19
21
  require "ldclient-rb/stream"
20
22
  require "ldclient-rb/polling"
21
- require "ldclient-rb/user_filter"
22
23
  require "ldclient-rb/simple_lru_cache"
23
24
  require "ldclient-rb/non_blocking_thread_pool"
24
- require "ldclient-rb/event_summarizer"
25
25
  require "ldclient-rb/events"
26
26
  require "ldclient-rb/requestor"
27
- require "ldclient-rb/file_data_source"
28
27
  require "ldclient-rb/integrations"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: launchdarkly-server-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.3.0
4
+ version: 8.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - LaunchDarkly
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-12-09 00:00:00.000000000 Z
11
+ date: 2023-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-dynamodb
@@ -30,14 +30,28 @@ dependencies:
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 2.2.10
33
+ version: 2.2.33
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 2.2.10
40
+ version: 2.2.33
41
+ - !ruby/object:Gem::Dependency
42
+ name: simplecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.21'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.21'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -58,42 +72,42 @@ dependencies:
58
72
  requirements:
59
73
  - - "~>"
60
74
  - !ruby/object:Gem::Version
61
- version: 2.4.2
75
+ version: '2.6'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
- version: 2.4.2
82
+ version: '2.6'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: redis
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: '4.2'
89
+ version: '5.0'
76
90
  type: :development
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '4.2'
96
+ version: '5.0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: connection_pool
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - "~>"
88
102
  - !ruby/object:Gem::Version
89
- version: 2.2.3
103
+ version: '2.3'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
- version: 2.2.3
110
+ version: '2.3'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: rspec_junit_formatter
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -151,19 +165,33 @@ dependencies:
151
165
  - !ruby/object:Gem::Version
152
166
  version: '1.7'
153
167
  - !ruby/object:Gem::Dependency
154
- name: oga
168
+ name: rubocop
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '1.37'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: '1.37'
181
+ - !ruby/object:Gem::Dependency
182
+ name: rubocop-performance
155
183
  requirement: !ruby/object:Gem::Requirement
156
184
  requirements:
157
185
  - - "~>"
158
186
  - !ruby/object:Gem::Version
159
- version: '2.2'
187
+ version: '1.15'
160
188
  type: :development
161
189
  prerelease: false
162
190
  version_requirements: !ruby/object:Gem::Requirement
163
191
  requirements:
164
192
  - - "~>"
165
193
  - !ruby/object:Gem::Version
166
- version: '2.2'
194
+ version: '1.15'
167
195
  - !ruby/object:Gem::Dependency
168
196
  name: semantic
169
197
  requirement: !ruby/object:Gem::Requirement
@@ -198,14 +226,14 @@ dependencies:
198
226
  requirements:
199
227
  - - '='
200
228
  - !ruby/object:Gem::Version
201
- version: 2.1.1
229
+ version: 2.2.2
202
230
  type: :runtime
203
231
  prerelease: false
204
232
  version_requirements: !ruby/object:Gem::Requirement
205
233
  requirements:
206
234
  - - '='
207
235
  - !ruby/object:Gem::Version
208
- version: 2.1.1
236
+ version: 2.2.2
209
237
  - !ruby/object:Gem::Dependency
210
238
  name: json
211
239
  requirement: !ruby/object:Gem::Requirement
@@ -253,27 +281,42 @@ files:
253
281
  - lib/ldclient-rb.rb
254
282
  - lib/ldclient-rb/cache_store.rb
255
283
  - lib/ldclient-rb/config.rb
284
+ - lib/ldclient-rb/context.rb
256
285
  - lib/ldclient-rb/evaluation_detail.rb
257
- - lib/ldclient-rb/event_summarizer.rb
258
286
  - lib/ldclient-rb/events.rb
259
287
  - lib/ldclient-rb/expiring_cache.rb
260
- - lib/ldclient-rb/file_data_source.rb
261
288
  - lib/ldclient-rb/flags_state.rb
262
289
  - lib/ldclient-rb/impl.rb
263
290
  - lib/ldclient-rb/impl/big_segments.rb
291
+ - lib/ldclient-rb/impl/broadcaster.rb
292
+ - lib/ldclient-rb/impl/context.rb
293
+ - lib/ldclient-rb/impl/context_filter.rb
294
+ - lib/ldclient-rb/impl/data_source.rb
295
+ - lib/ldclient-rb/impl/data_store.rb
296
+ - lib/ldclient-rb/impl/dependency_tracker.rb
264
297
  - lib/ldclient-rb/impl/diagnostic_events.rb
265
298
  - lib/ldclient-rb/impl/evaluator.rb
266
299
  - lib/ldclient-rb/impl/evaluator_bucketing.rb
300
+ - lib/ldclient-rb/impl/evaluator_helpers.rb
267
301
  - lib/ldclient-rb/impl/evaluator_operators.rb
268
- - lib/ldclient-rb/impl/event_factory.rb
269
302
  - lib/ldclient-rb/impl/event_sender.rb
303
+ - lib/ldclient-rb/impl/event_summarizer.rb
304
+ - lib/ldclient-rb/impl/event_types.rb
305
+ - lib/ldclient-rb/impl/flag_tracker.rb
270
306
  - lib/ldclient-rb/impl/integrations/consul_impl.rb
271
307
  - lib/ldclient-rb/impl/integrations/dynamodb_impl.rb
272
308
  - lib/ldclient-rb/impl/integrations/file_data_source.rb
273
309
  - lib/ldclient-rb/impl/integrations/redis_impl.rb
274
310
  - lib/ldclient-rb/impl/integrations/test_data/test_data_source.rb
311
+ - lib/ldclient-rb/impl/migrations/migrator.rb
312
+ - lib/ldclient-rb/impl/migrations/tracker.rb
313
+ - lib/ldclient-rb/impl/model/clause.rb
314
+ - lib/ldclient-rb/impl/model/feature_flag.rb
315
+ - lib/ldclient-rb/impl/model/preprocessed_data.rb
316
+ - lib/ldclient-rb/impl/model/segment.rb
275
317
  - lib/ldclient-rb/impl/model/serialization.rb
276
318
  - lib/ldclient-rb/impl/repeating_task.rb
319
+ - lib/ldclient-rb/impl/sampler.rb
277
320
  - lib/ldclient-rb/impl/store_client_wrapper.rb
278
321
  - lib/ldclient-rb/impl/store_data_set_sorter.rb
279
322
  - lib/ldclient-rb/impl/unbounded_pool.rb
@@ -290,14 +333,13 @@ files:
290
333
  - lib/ldclient-rb/interfaces.rb
291
334
  - lib/ldclient-rb/ldclient.rb
292
335
  - lib/ldclient-rb/memoized_value.rb
293
- - lib/ldclient-rb/newrelic.rb
336
+ - lib/ldclient-rb/migrations.rb
294
337
  - lib/ldclient-rb/non_blocking_thread_pool.rb
295
338
  - lib/ldclient-rb/polling.rb
296
- - lib/ldclient-rb/redis_store.rb
339
+ - lib/ldclient-rb/reference.rb
297
340
  - lib/ldclient-rb/requestor.rb
298
341
  - lib/ldclient-rb/simple_lru_cache.rb
299
342
  - lib/ldclient-rb/stream.rb
300
- - lib/ldclient-rb/user_filter.rb
301
343
  - lib/ldclient-rb/util.rb
302
344
  - lib/ldclient-rb/version.rb
303
345
  homepage: https://github.com/launchdarkly/ruby-server-sdk
@@ -312,14 +354,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
312
354
  requirements:
313
355
  - - ">="
314
356
  - !ruby/object:Gem::Version
315
- version: 2.5.0
357
+ version: 3.0.0
316
358
  required_rubygems_version: !ruby/object:Gem::Requirement
317
359
  requirements:
318
360
  - - ">="
319
361
  - !ruby/object:Gem::Version
320
362
  version: '0'
321
363
  requirements: []
322
- rubygems_version: 3.2.33
364
+ rubygems_version: 3.4.21
323
365
  signing_key:
324
366
  specification_version: 4
325
367
  summary: LaunchDarkly SDK for Ruby
@@ -1,55 +0,0 @@
1
-
2
- module LaunchDarkly
3
- # @private
4
- EventSummary = Struct.new(:start_date, :end_date, :counters)
5
-
6
- # Manages the state of summarizable information for the EventProcessor, including the
7
- # event counters and user deduplication. Note that the methods of this class are
8
- # deliberately not thread-safe; the EventProcessor is responsible for enforcing
9
- # synchronization across both the summarizer and the event queue.
10
- #
11
- # @private
12
- class EventSummarizer
13
- def initialize
14
- clear
15
- end
16
-
17
- # Adds this event to our counters, if it is a type of event we need to count.
18
- def summarize_event(event)
19
- if event[:kind] == "feature"
20
- counter_key = {
21
- key: event[:key],
22
- version: event[:version],
23
- variation: event[:variation]
24
- }
25
- c = @counters[counter_key]
26
- if c.nil?
27
- @counters[counter_key] = {
28
- value: event[:value],
29
- default: event[:default],
30
- count: 1
31
- }
32
- else
33
- c[:count] = c[:count] + 1
34
- end
35
- time = event[:creationDate]
36
- if !time.nil?
37
- @start_date = time if @start_date == 0 || time < @start_date
38
- @end_date = time if time > @end_date
39
- end
40
- end
41
- end
42
-
43
- # Returns a snapshot of the current summarized event data, and resets this state.
44
- def snapshot
45
- ret = EventSummary.new(@start_date, @end_date, @counters)
46
- ret
47
- end
48
-
49
- def clear
50
- @start_date = 0
51
- @end_date = 0
52
- @counters = {}
53
- end
54
- end
55
- end
@@ -1,23 +0,0 @@
1
- require "ldclient-rb/integrations/file_data"
2
-
3
- module LaunchDarkly
4
- #
5
- # Deprecated entry point for the file data source feature.
6
- #
7
- # The new preferred usage is {LaunchDarkly::Integrations::FileData#data_source}.
8
- #
9
- # @deprecated This is replaced by {LaunchDarkly::Integrations::FileData}.
10
- #
11
- class FileDataSource
12
- #
13
- # Deprecated entry point for the file data source feature.
14
- #
15
- # The new preferred usage is {LaunchDarkly::Integrations::FileData#data_source}.
16
- #
17
- # @deprecated This is replaced by {LaunchDarkly::Integrations::FileData#data_source}.
18
- #
19
- def self.factory(options={})
20
- LaunchDarkly::Integrations::FileData.data_source(options)
21
- end
22
- end
23
- end