launchdarkly-server-sdk 6.3.4 → 7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/lib/ldclient-rb/config.rb +121 -55
  3. data/lib/ldclient-rb/context.rb +487 -0
  4. data/lib/ldclient-rb/evaluation_detail.rb +20 -20
  5. data/lib/ldclient-rb/events.rb +77 -132
  6. data/lib/ldclient-rb/flags_state.rb +4 -4
  7. data/lib/ldclient-rb/impl/big_segments.rb +17 -17
  8. data/lib/ldclient-rb/impl/context.rb +96 -0
  9. data/lib/ldclient-rb/impl/context_filter.rb +145 -0
  10. data/lib/ldclient-rb/impl/diagnostic_events.rb +9 -10
  11. data/lib/ldclient-rb/impl/evaluator.rb +378 -139
  12. data/lib/ldclient-rb/impl/evaluator_bucketing.rb +40 -41
  13. data/lib/ldclient-rb/impl/evaluator_helpers.rb +50 -0
  14. data/lib/ldclient-rb/impl/evaluator_operators.rb +26 -55
  15. data/lib/ldclient-rb/impl/event_sender.rb +6 -6
  16. data/lib/ldclient-rb/impl/event_summarizer.rb +12 -7
  17. data/lib/ldclient-rb/impl/event_types.rb +18 -30
  18. data/lib/ldclient-rb/impl/integrations/consul_impl.rb +7 -7
  19. data/lib/ldclient-rb/impl/integrations/dynamodb_impl.rb +29 -29
  20. data/lib/ldclient-rb/impl/integrations/file_data_source.rb +8 -8
  21. data/lib/ldclient-rb/impl/integrations/redis_impl.rb +92 -12
  22. data/lib/ldclient-rb/impl/model/clause.rb +39 -0
  23. data/lib/ldclient-rb/impl/model/feature_flag.rb +213 -0
  24. data/lib/ldclient-rb/impl/model/preprocessed_data.rb +64 -0
  25. data/lib/ldclient-rb/impl/model/segment.rb +126 -0
  26. data/lib/ldclient-rb/impl/model/serialization.rb +54 -44
  27. data/lib/ldclient-rb/impl/repeating_task.rb +1 -1
  28. data/lib/ldclient-rb/impl/store_data_set_sorter.rb +2 -2
  29. data/lib/ldclient-rb/impl/unbounded_pool.rb +1 -1
  30. data/lib/ldclient-rb/impl/util.rb +59 -1
  31. data/lib/ldclient-rb/in_memory_store.rb +2 -2
  32. data/lib/ldclient-rb/integrations/consul.rb +1 -1
  33. data/lib/ldclient-rb/integrations/dynamodb.rb +1 -1
  34. data/lib/ldclient-rb/integrations/file_data.rb +3 -3
  35. data/lib/ldclient-rb/integrations/redis.rb +4 -4
  36. data/lib/ldclient-rb/integrations/test_data/flag_builder.rb +218 -62
  37. data/lib/ldclient-rb/integrations/test_data.rb +16 -12
  38. data/lib/ldclient-rb/integrations/util/store_wrapper.rb +9 -9
  39. data/lib/ldclient-rb/interfaces.rb +14 -14
  40. data/lib/ldclient-rb/ldclient.rb +94 -144
  41. data/lib/ldclient-rb/memoized_value.rb +1 -1
  42. data/lib/ldclient-rb/non_blocking_thread_pool.rb +1 -1
  43. data/lib/ldclient-rb/polling.rb +2 -2
  44. data/lib/ldclient-rb/reference.rb +274 -0
  45. data/lib/ldclient-rb/requestor.rb +7 -7
  46. data/lib/ldclient-rb/stream.rb +8 -9
  47. data/lib/ldclient-rb/util.rb +4 -19
  48. data/lib/ldclient-rb/version.rb +1 -1
  49. data/lib/ldclient-rb.rb +2 -3
  50. metadata +36 -17
  51. data/lib/ldclient-rb/file_data_source.rb +0 -23
  52. data/lib/ldclient-rb/newrelic.rb +0 -17
  53. data/lib/ldclient-rb/redis_store.rb +0 -88
  54. data/lib/ldclient-rb/user_filter.rb +0 -52
@@ -0,0 +1,274 @@
1
+ module LaunchDarkly
2
+ #
3
+ # Reference is an attribute name or path expression identifying a value
4
+ # within a Context.
5
+ #
6
+ # This type is mainly intended to be used internally by LaunchDarkly SDK and
7
+ # service code, where efficiency is a major concern so it's desirable to do
8
+ # any parsing or preprocessing just once. Applications are unlikely to need
9
+ # to use the Reference type directly.
10
+ #
11
+ # It can be used to retrieve a value with LDContext.get_value_for_reference()
12
+ # or to identify an attribute or nested value that should be considered
13
+ # private.
14
+ #
15
+ # Parsing and validation are done at the time that the Reference is
16
+ # constructed. If a Reference instance was created from an invalid string, it
17
+ # is considered invalid and its {Reference#error} attribute will return a
18
+ # non-nil error.
19
+ #
20
+ # ## Syntax
21
+ #
22
+ # The string representation of an attribute reference in LaunchDarkly JSON
23
+ # data uses the following syntax:
24
+ #
25
+ # If the first character is not a slash, the string is interpreted literally
26
+ # as an attribute name. An attribute name can contain any characters, but
27
+ # must not be empty.
28
+ #
29
+ # If the first character is a slash, the string is interpreted as a
30
+ # slash-delimited path where the first path component is an attribute name,
31
+ # and each subsequent path component is the name of a property in a JSON
32
+ # object. Any instances of the characters "/" or "~" in a path component are
33
+ # escaped as "~1" or "~0" respectively. This syntax deliberately resembles
34
+ # JSON Pointer, but no JSON Pointer behaviors other than those mentioned here
35
+ # are supported.
36
+ #
37
+ # ## Examples
38
+ #
39
+ # Suppose there is a context whose JSON implementation looks like this:
40
+ #
41
+ # {
42
+ # "kind": "user",
43
+ # "key": "value1",
44
+ # "address": {
45
+ # "street": {
46
+ # "line1": "value2",
47
+ # "line2": "value3"
48
+ # },
49
+ # "city": "value4"
50
+ # },
51
+ # "good/bad": "value5"
52
+ # }
53
+ #
54
+ # The attribute references "key" and "/key" would both point to "value1".
55
+ #
56
+ # The attribute reference "/address/street/line1" would point to "value2".
57
+ #
58
+ # The attribute references "good/bad" and "/good~1bad" would both point to
59
+ # "value5".
60
+ #
61
+ class Reference
62
+ ERR_EMPTY = 'empty reference'
63
+ private_constant :ERR_EMPTY
64
+
65
+ ERR_INVALID_ESCAPE_SEQUENCE = 'invalid escape sequence'
66
+ private_constant :ERR_INVALID_ESCAPE_SEQUENCE
67
+
68
+ ERR_DOUBLE_TRAILING_SLASH = 'double or trailing slash'
69
+ private_constant :ERR_DOUBLE_TRAILING_SLASH
70
+
71
+ #
72
+ # Returns nil for a valid Reference, or a non-nil error value for an
73
+ # invalid Reference.
74
+ #
75
+ # A Reference is invalid if the input string is empty, or starts with a
76
+ # slash but is not a valid slash-delimited path, or starts with a slash and
77
+ # contains an invalid escape sequence.
78
+ #
79
+ # Otherwise, the Reference is valid, but that does not guarantee that such
80
+ # an attribute exists in any given Context. For instance,
81
+ # Reference.create("name") is a valid Reference, but a specific Context
82
+ # might or might not have a name.
83
+ #
84
+ # See comments on the Reference type for more details of the attribute
85
+ # reference syntax.
86
+ #
87
+ # @return [String, nil]
88
+ #
89
+ attr_reader :error
90
+
91
+ #
92
+ # Returns the attribute reference as a string, in the same format provided
93
+ # to {#create}.
94
+ #
95
+ # If the Reference was created with {#create}, this value is identical to
96
+ # the original string. If it was created with {#create_literal}, the value
97
+ # may be different due to unescaping (for instance, an attribute whose name
98
+ # is "/a" would be represented as "~1a").
99
+ #
100
+ # @return [String, nil]
101
+ #
102
+ attr_reader :raw_path
103
+
104
+ def initialize(raw_path, components = [], error = nil)
105
+ @raw_path = raw_path
106
+ # @type [Array<Symbol>]
107
+ @components = components
108
+ @error = error
109
+ end
110
+ private_class_method :new
111
+
112
+ #
113
+ # Creates a Reference from a string. For the supported syntax and examples,
114
+ # see comments on the Reference type.
115
+ #
116
+ # This constructor always returns a Reference that preserves the original
117
+ # string, even if validation fails, so that accessing {#raw_path} (or
118
+ # serializing the Reference to JSON) will produce the original string. If
119
+ # validation fails, {#error} will return a non-nil error and any SDK method
120
+ # that takes this Reference as a parameter will consider it invalid.
121
+ #
122
+ # @param value [String, Symbol]
123
+ # @return [Reference]
124
+ #
125
+ def self.create(value)
126
+ unless value.is_a?(String) || value.is_a?(Symbol)
127
+ return new(value, [], ERR_EMPTY)
128
+ end
129
+
130
+ value = value.to_s if value.is_a?(Symbol)
131
+
132
+ return new(value, [], ERR_EMPTY) if value.empty? || value == "/"
133
+
134
+ unless value.start_with? "/"
135
+ return new(value, [value.to_sym])
136
+ end
137
+
138
+ if value.end_with? "/"
139
+ return new(value, [], ERR_DOUBLE_TRAILING_SLASH)
140
+ end
141
+
142
+ components = []
143
+ value[1..].split("/").each do |component|
144
+ if component.empty?
145
+ return new(value, [], ERR_DOUBLE_TRAILING_SLASH)
146
+ end
147
+
148
+ path, error = unescape_path(component)
149
+
150
+ if error
151
+ return new(value, [], error)
152
+ end
153
+
154
+ components << path.to_sym
155
+ end
156
+
157
+ new(value, components)
158
+ end
159
+
160
+ #
161
+ # create_literal is similar to {#create} except that it always
162
+ # interprets the string as a literal attribute name, never as a
163
+ # slash-delimited path expression. There is no escaping or unescaping, even
164
+ # if the name contains literal '/' or '~' characters. Since an attribute
165
+ # name can contain any characters, this method always returns a valid
166
+ # Reference unless the name is empty.
167
+ #
168
+ # For example: Reference.create_literal("name") is exactly equivalent to
169
+ # Reference.create("name"). Reference.create_literal("a/b") is exactly
170
+ # equivalent to Reference.create("a/b") (since the syntax used by {#create}
171
+ # treats the whole string as a literal as long as it does not start with a
172
+ # slash), or to Reference.create("/a~1b").
173
+ #
174
+ # @param value [String, Symbol]
175
+ # @return [Reference]
176
+ #
177
+ def self.create_literal(value)
178
+ unless value.is_a?(String) || value.is_a?(Symbol)
179
+ return new(value, [], ERR_EMPTY)
180
+ end
181
+
182
+ value = value.to_s if value.is_a?(Symbol)
183
+
184
+ return new(value, [], ERR_EMPTY) if value.empty?
185
+ return new(value, [value.to_sym]) if value[0] != '/'
186
+
187
+ escaped = "/" + value.gsub('~', '~0').gsub('/', '~1')
188
+ new(escaped, [value.to_sym])
189
+ end
190
+
191
+ #
192
+ # Returns the number of path components in the Reference.
193
+ #
194
+ # For a simple attribute reference such as "name" with no leading slash,
195
+ # this returns 1.
196
+ #
197
+ # For an attribute reference with a leading slash, it is the number of
198
+ # slash-delimited path components after the initial slash. For instance,
199
+ # NewRef("/a/b").Depth() returns 2.
200
+ #
201
+ # @return [Integer]
202
+ #
203
+ def depth
204
+ @components.size
205
+ end
206
+
207
+ #
208
+ # Retrieves a single path component from the attribute reference.
209
+ #
210
+ # For a simple attribute reference such as "name" with no leading slash, if
211
+ # index is zero, {#component} returns the attribute name as a symbol.
212
+ #
213
+ # For an attribute reference with a leading slash, if index is non-negative
214
+ # and less than {#depth}, Component returns the path component as a symbol.
215
+ #
216
+ # If index is out of range, it returns nil.
217
+ #
218
+ # Reference.create("a").component(0) # returns "a"
219
+ # Reference.create("/a/b").component(1) # returns "b"
220
+ #
221
+ # @param index [Integer]
222
+ # @return [Symbol, nil]
223
+ #
224
+ def component(index)
225
+ return nil if index < 0 || index >= depth
226
+
227
+ @components[index]
228
+ end
229
+
230
+ #
231
+ # Performs unescaping of attribute reference path components:
232
+ #
233
+ # "~1" becomes "/"
234
+ # "~0" becomes "~"
235
+ # "~" followed by any character other than "0" or "1" is invalid
236
+ #
237
+ # This method returns an array of two values. The first element of the
238
+ # array is the path if unescaping was valid; otherwise, it will be nil. The
239
+ # second value is an error string, or nil if the unescaping was successful.
240
+ #
241
+ # @param path [String]
242
+ # @return [Array([String, nil], [String, nil])] Returns a fixed size array.
243
+ #
244
+ private_class_method def self.unescape_path(path)
245
+ # If there are no tildes then there's definitely nothing to do
246
+ return path, nil unless path.include? '~'
247
+
248
+ out = ""
249
+ i = 0
250
+ while i < path.size
251
+ if path[i] != "~"
252
+ out << path[i]
253
+ i += 1
254
+ next
255
+ end
256
+
257
+ return nil, ERR_INVALID_ESCAPE_SEQUENCE if i + 1 == path.size
258
+
259
+ case path[i + 1]
260
+ when '0'
261
+ out << "~"
262
+ when '1'
263
+ out << '/'
264
+ else
265
+ return nil, ERR_INVALID_ESCAPE_SEQUENCE
266
+ end
267
+
268
+ i += 2
269
+ end
270
+
271
+ [out, nil]
272
+ end
273
+ end
274
+ end
@@ -31,9 +31,9 @@ module LaunchDarkly
31
31
 
32
32
  def request_all_data()
33
33
  all_data = JSON.parse(make_request("/sdk/latest-all"), symbolize_names: true)
34
- Impl::Model.make_all_store_data(all_data)
34
+ Impl::Model.make_all_store_data(all_data, @config.logger)
35
35
  end
36
-
36
+
37
37
  def stop
38
38
  begin
39
39
  @http_client.close
@@ -44,7 +44,7 @@ module LaunchDarkly
44
44
  private
45
45
 
46
46
  def request_single_item(kind, path)
47
- Impl::Model.deserialize(kind, make_request(path))
47
+ Impl::Model.deserialize(kind, make_request(path), @config.logger)
48
48
  end
49
49
 
50
50
  def make_request(path)
@@ -53,11 +53,11 @@ module LaunchDarkly
53
53
  Impl::Util.default_http_headers(@sdk_key, @config).each { |k, v| headers[k] = v }
54
54
  headers["Connection"] = "keep-alive"
55
55
  cached = @cache.read(uri)
56
- if !cached.nil?
56
+ unless cached.nil?
57
57
  headers["If-None-Match"] = cached.etag
58
58
  end
59
59
  response = @http_client.request("GET", uri, {
60
- headers: headers
60
+ headers: headers,
61
61
  })
62
62
  status = response.status.code
63
63
  # must fully read body for persistent connections
@@ -72,7 +72,7 @@ module LaunchDarkly
72
72
  end
73
73
  body = fix_encoding(body, response.headers["content-type"])
74
74
  etag = response.headers["etag"]
75
- @cache.write(uri, CacheEntry.new(etag, body)) if !etag.nil?
75
+ @cache.write(uri, CacheEntry.new(etag, body)) unless etag.nil?
76
76
  end
77
77
  body
78
78
  end
@@ -96,7 +96,7 @@ module LaunchDarkly
96
96
  break
97
97
  end
98
98
  end
99
- return [parts[0], charset]
99
+ [parts[0], charset]
100
100
  end
101
101
  end
102
102
  end
@@ -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
@@ -41,14 +41,14 @@ module LaunchDarkly
41
41
  return @ready unless @started.make_true
42
42
 
43
43
  @config.logger.info { "[LDClient] Initializing stream connection" }
44
-
44
+
45
45
  headers = Impl::Util.default_http_headers(@sdk_key, @config)
46
46
  opts = {
47
47
  headers: headers,
48
48
  read_timeout: READ_TIMEOUT_SECONDS,
49
49
  logger: @config.logger,
50
50
  socket_factory: @config.socket_factory,
51
- reconnect_time: @config.initial_reconnect_delay
51
+ reconnect_time: @config.initial_reconnect_delay,
52
52
  }
53
53
  log_connection_started
54
54
  @es = SSE::Client.new(@config.stream_uri + "/all", **opts) do |conn|
@@ -60,14 +60,14 @@ module LaunchDarkly
60
60
  status = err.status
61
61
  message = Util.http_error_message(status, "streaming connection", "will retry")
62
62
  @config.logger.error { "[LDClient] #{message}" }
63
- if !Util.http_error_recoverable?(status)
63
+ unless Util.http_error_recoverable?(status)
64
64
  @ready.set # if client was waiting on us, make it stop waiting - has no effect if already set
65
65
  stop
66
66
  end
67
67
  end
68
68
  }
69
69
  end
70
-
70
+
71
71
  @ready
72
72
  end
73
73
 
@@ -86,7 +86,7 @@ module LaunchDarkly
86
86
  @config.logger.debug { "[LDClient] Stream received #{method} message: #{message.data}" }
87
87
  if method == PUT
88
88
  message = JSON.parse(message.data, symbolize_names: true)
89
- all_data = Impl::Model.make_all_store_data(message[:data])
89
+ all_data = Impl::Model.make_all_store_data(message[:data], @config.logger)
90
90
  @feature_store.init(all_data)
91
91
  @initialized.make_true
92
92
  @config.logger.info { "[LDClient] Stream initialized" }
@@ -96,9 +96,8 @@ module LaunchDarkly
96
96
  for kind in [FEATURES, SEGMENTS]
97
97
  key = key_for_path(kind, data[:path])
98
98
  if key
99
- data = data[:data]
100
- Impl::Model.postprocess_item_after_deserializing!(kind, data)
101
- @feature_store.upsert(kind, data)
99
+ item = Impl::Model.deserialize(kind, data[:data], @config.logger)
100
+ @feature_store.upsert(kind, item)
102
101
  break
103
102
  end
104
103
  end
@@ -4,39 +4,24 @@ require "http"
4
4
  module LaunchDarkly
5
5
  # @private
6
6
  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
18
- end
19
- ret
20
- end
21
-
22
7
  def self.new_http_client(uri_s, config)
23
8
  http_client_options = {}
24
9
  if config.socket_factory
25
10
  http_client_options["socket_class"] = config.socket_factory
26
11
  end
27
12
  proxy = URI.parse(uri_s).find_proxy
28
- if !proxy.nil?
13
+ unless proxy.nil?
29
14
  http_client_options["proxy"] = {
30
15
  proxy_address: proxy.host,
31
16
  proxy_port: proxy.port,
32
17
  proxy_username: proxy.user,
33
- proxy_password: proxy.password
18
+ proxy_password: proxy.password,
34
19
  }
35
20
  end
36
- return HTTP::Client.new(http_client_options)
21
+ HTTP::Client.new(http_client_options)
37
22
  .timeout({
38
23
  read: config.read_timeout,
39
- connect: config.connect_timeout
24
+ connect: config.connect_timeout,
40
25
  })
41
26
  .persistent(uri_s)
42
27
  end
@@ -1,3 +1,3 @@
1
1
  module LaunchDarkly
2
- VERSION = "6.3.4"
2
+ VERSION = "7.0.0"
3
3
  end
data/lib/ldclient-rb.rb CHANGED
@@ -15,13 +15,12 @@ require "ldclient-rb/expiring_cache"
15
15
  require "ldclient-rb/memoized_value"
16
16
  require "ldclient-rb/in_memory_store"
17
17
  require "ldclient-rb/config"
18
- require "ldclient-rb/newrelic"
18
+ require "ldclient-rb/context"
19
+ require "ldclient-rb/reference"
19
20
  require "ldclient-rb/stream"
20
21
  require "ldclient-rb/polling"
21
- require "ldclient-rb/user_filter"
22
22
  require "ldclient-rb/simple_lru_cache"
23
23
  require "ldclient-rb/non_blocking_thread_pool"
24
24
  require "ldclient-rb/events"
25
25
  require "ldclient-rb/requestor"
26
- require "ldclient-rb/file_data_source"
27
26
  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.4
4
+ version: 7.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: 2022-06-30 00:00:00.000000000 Z
11
+ date: 2022-12-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-dynamodb
@@ -58,42 +58,42 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 2.4.2
61
+ version: '2.6'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 2.4.2
68
+ version: '2.6'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: redis
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '4.2'
75
+ version: '5.0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '4.2'
82
+ version: '5.0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: connection_pool
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 2.2.3
89
+ version: '2.3'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 2.2.3
96
+ version: '2.3'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rspec_junit_formatter
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -151,19 +151,33 @@ dependencies:
151
151
  - !ruby/object:Gem::Version
152
152
  version: '1.7'
153
153
  - !ruby/object:Gem::Dependency
154
- name: oga
154
+ name: rubocop
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: '1.37'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: '1.37'
167
+ - !ruby/object:Gem::Dependency
168
+ name: rubocop-performance
155
169
  requirement: !ruby/object:Gem::Requirement
156
170
  requirements:
157
171
  - - "~>"
158
172
  - !ruby/object:Gem::Version
159
- version: '2.2'
173
+ version: '1.15'
160
174
  type: :development
161
175
  prerelease: false
162
176
  version_requirements: !ruby/object:Gem::Requirement
163
177
  requirements:
164
178
  - - "~>"
165
179
  - !ruby/object:Gem::Version
166
- version: '2.2'
180
+ version: '1.15'
167
181
  - !ruby/object:Gem::Dependency
168
182
  name: semantic
169
183
  requirement: !ruby/object:Gem::Requirement
@@ -253,16 +267,19 @@ files:
253
267
  - lib/ldclient-rb.rb
254
268
  - lib/ldclient-rb/cache_store.rb
255
269
  - lib/ldclient-rb/config.rb
270
+ - lib/ldclient-rb/context.rb
256
271
  - lib/ldclient-rb/evaluation_detail.rb
257
272
  - lib/ldclient-rb/events.rb
258
273
  - lib/ldclient-rb/expiring_cache.rb
259
- - lib/ldclient-rb/file_data_source.rb
260
274
  - lib/ldclient-rb/flags_state.rb
261
275
  - lib/ldclient-rb/impl.rb
262
276
  - lib/ldclient-rb/impl/big_segments.rb
277
+ - lib/ldclient-rb/impl/context.rb
278
+ - lib/ldclient-rb/impl/context_filter.rb
263
279
  - lib/ldclient-rb/impl/diagnostic_events.rb
264
280
  - lib/ldclient-rb/impl/evaluator.rb
265
281
  - lib/ldclient-rb/impl/evaluator_bucketing.rb
282
+ - lib/ldclient-rb/impl/evaluator_helpers.rb
266
283
  - lib/ldclient-rb/impl/evaluator_operators.rb
267
284
  - lib/ldclient-rb/impl/event_sender.rb
268
285
  - lib/ldclient-rb/impl/event_summarizer.rb
@@ -272,6 +289,10 @@ files:
272
289
  - lib/ldclient-rb/impl/integrations/file_data_source.rb
273
290
  - lib/ldclient-rb/impl/integrations/redis_impl.rb
274
291
  - lib/ldclient-rb/impl/integrations/test_data/test_data_source.rb
292
+ - lib/ldclient-rb/impl/model/clause.rb
293
+ - lib/ldclient-rb/impl/model/feature_flag.rb
294
+ - lib/ldclient-rb/impl/model/preprocessed_data.rb
295
+ - lib/ldclient-rb/impl/model/segment.rb
275
296
  - lib/ldclient-rb/impl/model/serialization.rb
276
297
  - lib/ldclient-rb/impl/repeating_task.rb
277
298
  - lib/ldclient-rb/impl/store_client_wrapper.rb
@@ -290,14 +311,12 @@ files:
290
311
  - lib/ldclient-rb/interfaces.rb
291
312
  - lib/ldclient-rb/ldclient.rb
292
313
  - lib/ldclient-rb/memoized_value.rb
293
- - lib/ldclient-rb/newrelic.rb
294
314
  - lib/ldclient-rb/non_blocking_thread_pool.rb
295
315
  - lib/ldclient-rb/polling.rb
296
- - lib/ldclient-rb/redis_store.rb
316
+ - lib/ldclient-rb/reference.rb
297
317
  - lib/ldclient-rb/requestor.rb
298
318
  - lib/ldclient-rb/simple_lru_cache.rb
299
319
  - lib/ldclient-rb/stream.rb
300
- - lib/ldclient-rb/user_filter.rb
301
320
  - lib/ldclient-rb/util.rb
302
321
  - lib/ldclient-rb/version.rb
303
322
  homepage: https://github.com/launchdarkly/ruby-server-sdk
@@ -312,14 +331,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
312
331
  requirements:
313
332
  - - ">="
314
333
  - !ruby/object:Gem::Version
315
- version: 2.5.0
334
+ version: 2.7.0
316
335
  required_rubygems_version: !ruby/object:Gem::Requirement
317
336
  requirements:
318
337
  - - ">="
319
338
  - !ruby/object:Gem::Version
320
339
  version: '0'
321
340
  requirements: []
322
- rubygems_version: 3.3.17
341
+ rubygems_version: 3.4.1
323
342
  signing_key:
324
343
  specification_version: 4
325
344
  summary: LaunchDarkly SDK for Ruby
@@ -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
@@ -1,17 +0,0 @@
1
- module LaunchDarkly
2
- # @private
3
- class LDNewRelic
4
- begin
5
- require "newrelic_rpm"
6
- NR_ENABLED = defined?(::NewRelic::Agent.add_custom_parameters)
7
- rescue ScriptError, StandardError
8
- NR_ENABLED = false
9
- end
10
-
11
- def self.annotate_transaction(key, value)
12
- if NR_ENABLED
13
- ::NewRelic::Agent.add_custom_parameters(key.to_s => value.to_s)
14
- end
15
- end
16
- end
17
- end