launchdarkly-server-sdk 5.8.1 → 6.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +28 -122
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
  4. data/.github/ISSUE_TEMPLATE/config.yml +5 -0
  5. data/.gitignore +2 -1
  6. data/.ldrelease/build-docs.sh +18 -0
  7. data/.ldrelease/circleci/linux/execute.sh +18 -0
  8. data/.ldrelease/circleci/mac/execute.sh +18 -0
  9. data/.ldrelease/circleci/template/build.sh +29 -0
  10. data/.ldrelease/circleci/template/publish.sh +23 -0
  11. data/.ldrelease/circleci/template/set-gem-home.sh +7 -0
  12. data/.ldrelease/circleci/template/test.sh +10 -0
  13. data/.ldrelease/circleci/template/update-version.sh +8 -0
  14. data/.ldrelease/circleci/windows/execute.ps1 +19 -0
  15. data/.ldrelease/config.yml +14 -2
  16. data/CHANGELOG.md +29 -0
  17. data/CONTRIBUTING.md +1 -1
  18. data/README.md +4 -3
  19. data/azure-pipelines.yml +1 -1
  20. data/docs/Makefile +26 -0
  21. data/docs/index.md +9 -0
  22. data/launchdarkly-server-sdk.gemspec +16 -16
  23. data/lib/ldclient-rb.rb +0 -1
  24. data/lib/ldclient-rb/config.rb +15 -3
  25. data/lib/ldclient-rb/evaluation_detail.rb +324 -0
  26. data/lib/ldclient-rb/events.rb +6 -7
  27. data/lib/ldclient-rb/file_data_source.rb +1 -1
  28. data/lib/ldclient-rb/impl/evaluator.rb +231 -0
  29. data/lib/ldclient-rb/impl/evaluator_bucketing.rb +87 -0
  30. data/lib/ldclient-rb/impl/evaluator_operators.rb +160 -0
  31. data/lib/ldclient-rb/impl/event_factory.rb +28 -0
  32. data/lib/ldclient-rb/impl/event_sender.rb +56 -40
  33. data/lib/ldclient-rb/impl/integrations/consul_impl.rb +5 -5
  34. data/lib/ldclient-rb/impl/integrations/dynamodb_impl.rb +5 -5
  35. data/lib/ldclient-rb/impl/integrations/redis_impl.rb +5 -7
  36. data/lib/ldclient-rb/impl/model/serialization.rb +62 -0
  37. data/lib/ldclient-rb/impl/unbounded_pool.rb +34 -0
  38. data/lib/ldclient-rb/ldclient.rb +36 -15
  39. data/lib/ldclient-rb/polling.rb +1 -4
  40. data/lib/ldclient-rb/requestor.rb +25 -15
  41. data/lib/ldclient-rb/stream.rb +9 -6
  42. data/lib/ldclient-rb/util.rb +12 -8
  43. data/lib/ldclient-rb/version.rb +1 -1
  44. data/spec/evaluation_detail_spec.rb +135 -0
  45. data/spec/event_sender_spec.rb +20 -2
  46. data/spec/events_spec.rb +10 -0
  47. data/spec/http_util.rb +11 -1
  48. data/spec/impl/evaluator_bucketing_spec.rb +216 -0
  49. data/spec/impl/evaluator_clause_spec.rb +55 -0
  50. data/spec/impl/evaluator_operators_spec.rb +141 -0
  51. data/spec/impl/evaluator_rule_spec.rb +128 -0
  52. data/spec/impl/evaluator_segment_spec.rb +125 -0
  53. data/spec/impl/evaluator_spec.rb +349 -0
  54. data/spec/impl/evaluator_spec_base.rb +75 -0
  55. data/spec/impl/event_factory_spec.rb +108 -0
  56. data/spec/impl/model/serialization_spec.rb +41 -0
  57. data/spec/launchdarkly-server-sdk_spec.rb +1 -1
  58. data/spec/ldclient_end_to_end_spec.rb +34 -0
  59. data/spec/ldclient_spec.rb +64 -12
  60. data/spec/polling_spec.rb +2 -2
  61. data/spec/redis_feature_store_spec.rb +2 -2
  62. data/spec/requestor_spec.rb +11 -11
  63. metadata +92 -48
  64. data/.yardopts +0 -9
  65. data/Gemfile.lock +0 -89
  66. data/lib/ldclient-rb/evaluation.rb +0 -462
  67. data/scripts/gendocs.sh +0 -11
  68. data/scripts/release.sh +0 -27
  69. data/spec/evaluation_spec.rb +0 -789
@@ -0,0 +1,41 @@
1
+ require "spec_helper"
2
+
3
+ module LaunchDarkly
4
+ module Impl
5
+ module Model
6
+ describe "model serialization" do
7
+ it "serializes flag" do
8
+ flag = { key: "flagkey", version: 1 }
9
+ json = Model.serialize(FEATURES, flag)
10
+ expect(JSON.parse(json, symbolize_names: true)).to eq flag
11
+ end
12
+
13
+ it "serializes segment" do
14
+ segment = { key: "segkey", version: 1 }
15
+ json = Model.serialize(SEGMENTS, segment)
16
+ expect(JSON.parse(json, symbolize_names: true)).to eq segment
17
+ end
18
+
19
+ it "serializes arbitrary data kind" do
20
+ thing = { key: "thingkey", name: "me" }
21
+ json = Model.serialize({ name: "things" }, thing)
22
+ expect(JSON.parse(json, symbolize_names: true)).to eq thing
23
+ end
24
+
25
+ it "deserializes flag with no rules or prerequisites" do
26
+ flag_in = { key: "flagkey", version: 1 }
27
+ json = Model.serialize(FEATURES, flag_in)
28
+ flag_out = Model.deserialize(FEATURES, json)
29
+ expect(flag_out).to eq flag_in
30
+ end
31
+
32
+ it "deserializes segment" do
33
+ segment_in = { key: "segkey", version: 1 }
34
+ json = Model.serialize(SEGMENTS, segment_in)
35
+ segment_out = Model.deserialize(SEGMENTS, json)
36
+ expect(segment_out).to eq segment_in
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -4,7 +4,7 @@ require "bundler"
4
4
  describe LaunchDarkly do
5
5
  it "can be automatically loaded by Bundler.require" do
6
6
  ldclient_loaded =
7
- Bundler.with_clean_env do
7
+ Bundler.with_unbundled_env do
8
8
  Kernel.system("ruby", "./spec/launchdarkly-server-sdk_spec_autoloadtest.rb")
9
9
  end
10
10
 
@@ -80,6 +80,7 @@ module LaunchDarkly
80
80
 
81
81
  req, body = events_server.await_request_with_body
82
82
  expect(req.header['authorization']).to eq [ SDK_KEY ]
83
+ expect(req.header['connection']).to eq [ "Keep-Alive" ]
83
84
  data = JSON.parse(body)
84
85
  expect(data.length).to eq 1
85
86
  expect(data[0]["kind"]).to eq "identify"
@@ -111,6 +112,7 @@ module LaunchDarkly
111
112
  req = req0.path == "/diagnostic" ? req0 : req1
112
113
  body = req0.path == "/diagnostic" ? body0 : body1
113
114
  expect(req.header['authorization']).to eq [ SDK_KEY ]
115
+ expect(req.header['connection']).to eq [ "Keep-Alive" ]
114
116
  data = JSON.parse(body)
115
117
  expect(data["kind"]).to eq "diagnostic-init"
116
118
  end
@@ -118,6 +120,38 @@ module LaunchDarkly
118
120
  end
119
121
  end
120
122
 
123
+ it "can use socket factory" do
124
+ with_server do |poll_server|
125
+ with_server do |events_server|
126
+ events_server.setup_ok_response("/bulk", "")
127
+ poll_server.setup_ok_response("/sdk/latest-all", '{"flags":{},"segments":{}}', "application/json")
128
+
129
+ config = Config.new(
130
+ stream: false,
131
+ base_uri: "http://polling.com",
132
+ events_uri: "http://events.com",
133
+ diagnostic_opt_out: true,
134
+ logger: NullLogger.new,
135
+ socket_factory: SocketFactoryFromHash.new({
136
+ "polling.com" => poll_server.port,
137
+ "events.com" => events_server.port
138
+ })
139
+ )
140
+ with_client(config) do |client|
141
+ client.identify(USER)
142
+ client.flush
143
+
144
+ req, body = events_server.await_request_with_body
145
+ expect(req.header['authorization']).to eq [ SDK_KEY ]
146
+ expect(req.header['connection']).to eq [ "Keep-Alive" ]
147
+ data = JSON.parse(body)
148
+ expect(data.length).to eq 1
149
+ expect(data[0]["kind"]).to eq "identify"
150
+ end
151
+ end
152
+ end
153
+ end
154
+
121
155
  # TODO: TLS tests with self-signed cert
122
156
  end
123
157
  end
@@ -25,6 +25,12 @@ describe LaunchDarkly::LDClient do
25
25
  }
26
26
  }
27
27
  end
28
+ let(:user_anonymous) do
29
+ {
30
+ key: "anonymous@test.com",
31
+ anonymous: true
32
+ }
33
+ end
28
34
  let(:numeric_key_user) do
29
35
  {
30
36
  key: 33,
@@ -139,20 +145,30 @@ describe LaunchDarkly::LDClient do
139
145
  client.variation("key", user, "default")
140
146
  end
141
147
 
142
- it "queues a feature event for an existing feature when user is nil" do
148
+ it "does not send an event if user is nil" do
149
+ config.feature_store.init({ LaunchDarkly::FEATURES => {} })
150
+ config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
151
+ expect(event_processor).not_to receive(:add_event)
152
+ expect(logger).to receive(:error)
153
+ client.variation("key", nil, "default")
154
+ end
155
+
156
+ it "queues a feature event for an existing feature when user is anonymous" do
143
157
  config.feature_store.init({ LaunchDarkly::FEATURES => {} })
144
158
  config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
145
159
  expect(event_processor).to receive(:add_event).with(hash_including(
146
160
  kind: "feature",
147
161
  key: "key",
148
162
  version: 100,
149
- user: nil,
150
- value: "default",
163
+ contextKind: "anonymousUser",
164
+ user: user_anonymous,
165
+ variation: 0,
166
+ value: "value",
151
167
  default: "default",
152
168
  trackEvents: true,
153
169
  debugEventsUntilDate: 1000
154
170
  ))
155
- client.variation("key", nil, "default")
171
+ client.variation("key", user_anonymous, "default")
156
172
  end
157
173
 
158
174
  it "queues a feature event for an existing feature when user key is nil" do
@@ -197,7 +213,7 @@ describe LaunchDarkly::LDClient do
197
213
  value: 'value',
198
214
  default: 'default',
199
215
  trackEvents: true,
200
- reason: { kind: 'RULE_MATCH', ruleIndex: 0, ruleId: 'id' }
216
+ reason: LaunchDarkly::EvaluationReason::rule_match(0, 'id')
201
217
  ))
202
218
  client.variation('flag', user, 'default')
203
219
  end
@@ -222,7 +238,7 @@ describe LaunchDarkly::LDClient do
222
238
  value: 'value',
223
239
  default: 'default',
224
240
  trackEvents: true,
225
- reason: { kind: 'FALLTHROUGH' }
241
+ reason: LaunchDarkly::EvaluationReason::fallthrough
226
242
  ))
227
243
  client.variation('flag', user, 'default')
228
244
  end
@@ -234,20 +250,22 @@ describe LaunchDarkly::LDClient do
234
250
 
235
251
  it "returns the default value if the client is offline" do
236
252
  result = offline_client.variation_detail("doesntmatter", user, "default")
237
- expected = LaunchDarkly::EvaluationDetail.new("default", nil, { kind: 'ERROR', errorKind: 'CLIENT_NOT_READY' })
253
+ expected = LaunchDarkly::EvaluationDetail.new("default", nil,
254
+ LaunchDarkly::EvaluationReason::error(LaunchDarkly::EvaluationReason::ERROR_CLIENT_NOT_READY))
238
255
  expect(result).to eq expected
239
256
  end
240
257
 
241
258
  it "returns the default value for an unknown feature" do
242
259
  result = client.variation_detail("badkey", user, "default")
243
- expected = LaunchDarkly::EvaluationDetail.new("default", nil, { kind: 'ERROR', errorKind: 'FLAG_NOT_FOUND'})
260
+ expected = LaunchDarkly::EvaluationDetail.new("default", nil,
261
+ LaunchDarkly::EvaluationReason::error(LaunchDarkly::EvaluationReason::ERROR_FLAG_NOT_FOUND))
244
262
  expect(result).to eq expected
245
263
  end
246
264
 
247
265
  it "queues a feature request event for an unknown feature" do
248
266
  expect(event_processor).to receive(:add_event).with(hash_including(
249
267
  kind: "feature", key: "badkey", user: user, value: "default", default: "default",
250
- reason: { kind: 'ERROR', errorKind: 'FLAG_NOT_FOUND' }
268
+ reason: LaunchDarkly::EvaluationReason::error(LaunchDarkly::EvaluationReason::ERROR_FLAG_NOT_FOUND)
251
269
  ))
252
270
  client.variation_detail("badkey", user, "default")
253
271
  end
@@ -256,7 +274,7 @@ describe LaunchDarkly::LDClient do
256
274
  config.feature_store.init({ LaunchDarkly::FEATURES => {} })
257
275
  config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
258
276
  result = client.variation_detail("key", user, "default")
259
- expected = LaunchDarkly::EvaluationDetail.new("value", 0, { kind: 'OFF' })
277
+ expected = LaunchDarkly::EvaluationDetail.new("value", 0, LaunchDarkly::EvaluationReason::off)
260
278
  expect(result).to eq expected
261
279
  end
262
280
 
@@ -265,7 +283,7 @@ describe LaunchDarkly::LDClient do
265
283
  config.feature_store.init({ LaunchDarkly::FEATURES => {} })
266
284
  config.feature_store.upsert(LaunchDarkly::FEATURES, empty_feature)
267
285
  result = client.variation_detail("key", user, "default")
268
- expected = LaunchDarkly::EvaluationDetail.new("default", nil, { kind: 'OFF' })
286
+ expected = LaunchDarkly::EvaluationDetail.new("default", nil, LaunchDarkly::EvaluationReason::off)
269
287
  expect(result).to eq expected
270
288
  expect(result.default_value?).to be true
271
289
  end
@@ -283,10 +301,18 @@ describe LaunchDarkly::LDClient do
283
301
  default: "default",
284
302
  trackEvents: true,
285
303
  debugEventsUntilDate: 1000,
286
- reason: { kind: "OFF" }
304
+ reason: LaunchDarkly::EvaluationReason::off
287
305
  ))
288
306
  client.variation_detail("key", user, "default")
289
307
  end
308
+
309
+ it "does not send an event if user is nil" do
310
+ config.feature_store.init({ LaunchDarkly::FEATURES => {} })
311
+ config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
312
+ expect(event_processor).not_to receive(:add_event)
313
+ expect(logger).to receive(:error)
314
+ client.variation_detail("key", nil, "default")
315
+ end
290
316
  end
291
317
 
292
318
  describe '#all_flags' do
@@ -453,6 +479,12 @@ describe LaunchDarkly::LDClient do
453
479
  client.track("custom_event_name", user, nil, 1.5)
454
480
  end
455
481
 
482
+ it "includes contextKind with anonymous user" do
483
+ expect(event_processor).to receive(:add_event).with(hash_including(
484
+ kind: "custom", key: "custom_event_name", user: user_anonymous, metricValue: 2.2, contextKind: "anonymousUser"))
485
+ client.track("custom_event_name", user_anonymous, nil, 2.2)
486
+ end
487
+
456
488
  it "sanitizes the user in the event" do
457
489
  expect(event_processor).to receive(:add_event).with(hash_including(user: sanitized_numeric_key_user))
458
490
  client.track("custom_event_name", numeric_key_user, nil)
@@ -471,6 +503,26 @@ describe LaunchDarkly::LDClient do
471
503
  end
472
504
  end
473
505
 
506
+ describe '#alias' do
507
+ it "queues up an alias event" do
508
+ expect(event_processor).to receive(:add_event).with(hash_including(
509
+ kind: "alias", key: user[:key], contextKind: "user", previousKey: user_anonymous[:key], previousContextKind: "anonymousUser"))
510
+ client.alias(user, user_anonymous)
511
+ end
512
+
513
+ it "does not send an event, and logs a warning, if user is nil" do
514
+ expect(event_processor).not_to receive(:add_event)
515
+ expect(logger).to receive(:warn)
516
+ client.alias(nil, nil)
517
+ end
518
+
519
+ it "does not send an event, and logs a warning, if user key is nil" do
520
+ expect(event_processor).not_to receive(:add_event)
521
+ expect(logger).to receive(:warn)
522
+ client.alias(user_without_key, user_without_key)
523
+ end
524
+ end
525
+
474
526
  describe '#identify' do
475
527
  it "queues up an identify event" do
476
528
  expect(event_processor).to receive(:add_event).with(hash_including(kind: "identify", key: user[:key], user: user))
data/spec/polling_spec.rb CHANGED
@@ -19,10 +19,10 @@ describe LaunchDarkly::PollingProcessor do
19
19
  flag = { key: 'flagkey', version: 1 }
20
20
  segment = { key: 'segkey', version: 1 }
21
21
  all_data = {
22
- flags: {
22
+ LaunchDarkly::FEATURES => {
23
23
  flagkey: flag
24
24
  },
25
- segments: {
25
+ LaunchDarkly::SEGMENTS => {
26
26
  segkey: segment
27
27
  }
28
28
  }
@@ -1,5 +1,5 @@
1
- require "connection_pool"
2
1
  require "feature_store_spec_base"
2
+ require "connection_pool"
3
3
  require "json"
4
4
  require "redis"
5
5
  require "spec_helper"
@@ -28,7 +28,7 @@ end
28
28
 
29
29
  describe LaunchDarkly::RedisFeatureStore do
30
30
  subject { LaunchDarkly::RedisFeatureStore }
31
-
31
+
32
32
  break if ENV['LD_SKIP_DATABASE_TESTS'] == '1'
33
33
 
34
34
  # These tests will all fail if there isn't a Redis instance running on the default port.
@@ -35,7 +35,7 @@ describe LaunchDarkly::Requestor do
35
35
  with_requestor(server.base_uri.to_s) do |requestor|
36
36
  server.setup_ok_response("/", expected_data.to_json)
37
37
  data = requestor.request_all_data()
38
- expect(data).to eq expected_data
38
+ expect(data).to eq LaunchDarkly::Impl::Model.make_all_store_data(expected_data)
39
39
  end
40
40
  end
41
41
  end
@@ -91,7 +91,7 @@ describe LaunchDarkly::Requestor do
91
91
  data = requestor.request_all_data()
92
92
  expect(server.requests.count).to eq 2
93
93
  expect(server.requests[1].header).to include({ "if-none-match" => [ etag ] })
94
- expect(data).to eq expected_data
94
+ expect(data).to eq LaunchDarkly::Impl::Model.make_all_store_data(expected_data)
95
95
  end
96
96
  end
97
97
  end
@@ -109,14 +109,14 @@ describe LaunchDarkly::Requestor do
109
109
  res["ETag"] = etag1
110
110
  end
111
111
  data = requestor.request_all_data()
112
- expect(data).to eq expected_data1
112
+ expect(data).to eq LaunchDarkly::Impl::Model.make_all_store_data(expected_data1)
113
113
  expect(server.requests.count).to eq 1
114
114
 
115
115
  server.setup_response("/") do |req, res|
116
116
  res.status = 304
117
117
  end
118
118
  data = requestor.request_all_data()
119
- expect(data).to eq expected_data1
119
+ expect(data).to eq LaunchDarkly::Impl::Model.make_all_store_data(expected_data1)
120
120
  expect(server.requests.count).to eq 2
121
121
  expect(server.requests[1].header).to include({ "if-none-match" => [ etag1 ] })
122
122
 
@@ -126,7 +126,7 @@ describe LaunchDarkly::Requestor do
126
126
  res["ETag"] = etag2
127
127
  end
128
128
  data = requestor.request_all_data()
129
- expect(data).to eq expected_data2
129
+ expect(data).to eq LaunchDarkly::Impl::Model.make_all_store_data(expected_data2)
130
130
  expect(server.requests.count).to eq 3
131
131
  expect(server.requests[2].header).to include({ "if-none-match" => [ etag1 ] })
132
132
 
@@ -134,7 +134,7 @@ describe LaunchDarkly::Requestor do
134
134
  res.status = 304
135
135
  end
136
136
  data = requestor.request_all_data()
137
- expect(data).to eq expected_data2
137
+ expect(data).to eq LaunchDarkly::Impl::Model.make_all_store_data(expected_data2)
138
138
  expect(server.requests.count).to eq 4
139
139
  expect(server.requests[3].header).to include({ "if-none-match" => [ etag2 ] })
140
140
  end
@@ -147,7 +147,7 @@ describe LaunchDarkly::Requestor do
147
147
  server.setup_ok_response("/sdk/latest-all", content, "application/json")
148
148
  with_requestor(server.base_uri.to_s) do |requestor|
149
149
  data = requestor.request_all_data
150
- expect(data).to eq(JSON.parse(content, symbolize_names: true))
150
+ expect(data).to eq(LaunchDarkly::Impl::Model.make_all_store_data(JSON.parse(content, symbolize_names: true)))
151
151
  end
152
152
  end
153
153
  end
@@ -159,7 +159,7 @@ describe LaunchDarkly::Requestor do
159
159
  "text/plain; charset=ISO-8859-2")
160
160
  with_requestor(server.base_uri.to_s) do |requestor|
161
161
  data = requestor.request_all_data
162
- expect(data).to eq(JSON.parse(content, symbolize_names: true))
162
+ expect(data).to eq(LaunchDarkly::Impl::Model.make_all_store_data(JSON.parse(content, symbolize_names: true)))
163
163
  end
164
164
  end
165
165
  end
@@ -176,15 +176,15 @@ describe LaunchDarkly::Requestor do
176
176
  end
177
177
 
178
178
  it "can use a proxy server" do
179
- content = '{"flags": {"flagkey": {"key": "flagkey"}}}'
179
+ expected_data = { flags: { flagkey: { key: "flagkey" } } }
180
180
  with_server do |server|
181
- server.setup_ok_response("/sdk/latest-all", content, "application/json", { "etag" => "x" })
181
+ server.setup_ok_response("/sdk/latest-all", expected_data.to_json, "application/json", { "etag" => "x" })
182
182
  with_server(StubProxyServer.new) do |proxy|
183
183
  begin
184
184
  ENV["http_proxy"] = proxy.base_uri.to_s
185
185
  with_requestor(server.base_uri.to_s) do |requestor|
186
186
  data = requestor.request_all_data
187
- expect(data).to eq(JSON.parse(content, symbolize_names: true))
187
+ expect(data).to eq(LaunchDarkly::Impl::Model.make_all_store_data(expected_data))
188
188
  end
189
189
  ensure
190
190
  ENV["http_proxy"] = nil
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: 5.8.1
4
+ version: 6.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - LaunchDarkly
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-09 00:00:00.000000000 Z
11
+ date: 2021-06-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-dynamodb
@@ -16,154 +16,154 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.18'
19
+ version: '1.57'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.18'
26
+ version: '1.57'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.17'
33
+ version: '2.1'
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: '1.17'
40
+ version: '2.1'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '3.2'
47
+ version: '3.10'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '3.2'
54
+ version: '3.10'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: diplomat
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 2.0.2
61
+ version: 2.4.2
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.0.2
68
+ version: 2.4.2
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: 3.3.5
75
+ version: '4.2'
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: 3.3.5
82
+ version: '4.2'
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.1.2
89
+ version: 2.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.1.2
96
+ version: 2.2.3
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: rspec_junit_formatter
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - "~>"
102
102
  - !ruby/object:Gem::Version
103
- version: 0.3.0
103
+ version: '0.4'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
- version: 0.3.0
110
+ version: '0.4'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: timecop
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 0.9.1
117
+ version: '0.9'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
- version: 0.9.1
124
+ version: '0.9'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: listen
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: '3.0'
131
+ version: '3.3'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
- version: '3.0'
138
+ version: '3.3'
139
139
  - !ruby/object:Gem::Dependency
140
- name: ffi
140
+ name: webrick
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - "<="
143
+ - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '1.12'
145
+ version: '1.7'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - "<="
150
+ - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: '1.12'
152
+ version: '1.7'
153
153
  - !ruby/object:Gem::Dependency
154
- name: faraday
154
+ name: oga
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
157
  - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: '0.17'
159
+ version: '2.2'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: '0.17'
166
+ version: '2.2'
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: semantic
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -184,28 +184,28 @@ dependencies:
184
184
  requirements:
185
185
  - - "~>"
186
186
  - !ruby/object:Gem::Version
187
- version: '1.0'
187
+ version: '1.1'
188
188
  type: :runtime
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - "~>"
193
193
  - !ruby/object:Gem::Version
194
- version: '1.0'
194
+ version: '1.1'
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: ld-eventsource
197
197
  requirement: !ruby/object:Gem::Requirement
198
198
  requirements:
199
- - - '='
199
+ - - "~>"
200
200
  - !ruby/object:Gem::Version
201
- version: 1.0.3
201
+ version: '2.0'
202
202
  type: :runtime
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
- - - '='
206
+ - - "~>"
207
207
  - !ruby/object:Gem::Version
208
- version: 1.0.3
208
+ version: '2.0'
209
209
  - !ruby/object:Gem::Dependency
210
210
  name: json
211
211
  requirement: !ruby/object:Gem::Requirement
@@ -220,6 +220,20 @@ dependencies:
220
220
  - - "~>"
221
221
  - !ruby/object:Gem::Version
222
222
  version: 2.3.1
223
+ - !ruby/object:Gem::Dependency
224
+ name: http
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - "~>"
228
+ - !ruby/object:Gem::Version
229
+ version: 4.4.1
230
+ type: :runtime
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - "~>"
235
+ - !ruby/object:Gem::Version
236
+ version: 4.4.1
223
237
  description: Official LaunchDarkly SDK for Ruby
224
238
  email:
225
239
  - team@launchdarkly.com
@@ -229,29 +243,39 @@ extra_rdoc_files: []
229
243
  files:
230
244
  - ".circleci/config.yml"
231
245
  - ".github/ISSUE_TEMPLATE/bug_report.md"
246
+ - ".github/ISSUE_TEMPLATE/config.yml"
232
247
  - ".github/ISSUE_TEMPLATE/feature_request.md"
233
248
  - ".github/pull_request_template.md"
234
249
  - ".gitignore"
235
250
  - ".hound.yml"
251
+ - ".ldrelease/build-docs.sh"
252
+ - ".ldrelease/circleci/linux/execute.sh"
253
+ - ".ldrelease/circleci/mac/execute.sh"
254
+ - ".ldrelease/circleci/template/build.sh"
255
+ - ".ldrelease/circleci/template/publish.sh"
256
+ - ".ldrelease/circleci/template/set-gem-home.sh"
257
+ - ".ldrelease/circleci/template/test.sh"
258
+ - ".ldrelease/circleci/template/update-version.sh"
259
+ - ".ldrelease/circleci/windows/execute.ps1"
236
260
  - ".ldrelease/config.yml"
237
261
  - ".rspec"
238
262
  - ".rubocop.yml"
239
263
  - ".simplecov"
240
- - ".yardopts"
241
264
  - CHANGELOG.md
242
265
  - CODEOWNERS
243
266
  - CONTRIBUTING.md
244
267
  - Gemfile
245
- - Gemfile.lock
246
268
  - LICENSE.txt
247
269
  - README.md
248
270
  - azure-pipelines.yml
271
+ - docs/Makefile
272
+ - docs/index.md
249
273
  - launchdarkly-server-sdk.gemspec
250
274
  - lib/launchdarkly-server-sdk.rb
251
275
  - lib/ldclient-rb.rb
252
276
  - lib/ldclient-rb/cache_store.rb
253
277
  - lib/ldclient-rb/config.rb
254
- - lib/ldclient-rb/evaluation.rb
278
+ - lib/ldclient-rb/evaluation_detail.rb
255
279
  - lib/ldclient-rb/event_summarizer.rb
256
280
  - lib/ldclient-rb/events.rb
257
281
  - lib/ldclient-rb/expiring_cache.rb
@@ -259,13 +283,18 @@ files:
259
283
  - lib/ldclient-rb/flags_state.rb
260
284
  - lib/ldclient-rb/impl.rb
261
285
  - lib/ldclient-rb/impl/diagnostic_events.rb
286
+ - lib/ldclient-rb/impl/evaluator.rb
287
+ - lib/ldclient-rb/impl/evaluator_bucketing.rb
288
+ - lib/ldclient-rb/impl/evaluator_operators.rb
262
289
  - lib/ldclient-rb/impl/event_factory.rb
263
290
  - lib/ldclient-rb/impl/event_sender.rb
264
291
  - lib/ldclient-rb/impl/integrations/consul_impl.rb
265
292
  - lib/ldclient-rb/impl/integrations/dynamodb_impl.rb
266
293
  - lib/ldclient-rb/impl/integrations/redis_impl.rb
294
+ - lib/ldclient-rb/impl/model/serialization.rb
267
295
  - lib/ldclient-rb/impl/store_client_wrapper.rb
268
296
  - lib/ldclient-rb/impl/store_data_set_sorter.rb
297
+ - lib/ldclient-rb/impl/unbounded_pool.rb
269
298
  - lib/ldclient-rb/impl/util.rb
270
299
  - lib/ldclient-rb/in_memory_store.rb
271
300
  - lib/ldclient-rb/integrations.rb
@@ -286,11 +315,9 @@ files:
286
315
  - lib/ldclient-rb/user_filter.rb
287
316
  - lib/ldclient-rb/util.rb
288
317
  - lib/ldclient-rb/version.rb
289
- - scripts/gendocs.sh
290
- - scripts/release.sh
291
318
  - spec/config_spec.rb
292
319
  - spec/diagnostic_events_spec.rb
293
- - spec/evaluation_spec.rb
320
+ - spec/evaluation_detail_spec.rb
294
321
  - spec/event_sender_spec.rb
295
322
  - spec/event_summarizer_spec.rb
296
323
  - spec/events_spec.rb
@@ -302,6 +329,15 @@ files:
302
329
  - spec/fixtures/user.json
303
330
  - spec/flags_state_spec.rb
304
331
  - spec/http_util.rb
332
+ - spec/impl/evaluator_bucketing_spec.rb
333
+ - spec/impl/evaluator_clause_spec.rb
334
+ - spec/impl/evaluator_operators_spec.rb
335
+ - spec/impl/evaluator_rule_spec.rb
336
+ - spec/impl/evaluator_segment_spec.rb
337
+ - spec/impl/evaluator_spec.rb
338
+ - spec/impl/evaluator_spec_base.rb
339
+ - spec/impl/event_factory_spec.rb
340
+ - spec/impl/model/serialization_spec.rb
305
341
  - spec/in_memory_feature_store_spec.rb
306
342
  - spec/integrations/consul_feature_store_spec.rb
307
343
  - spec/integrations/dynamodb_feature_store_spec.rb
@@ -334,22 +370,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
334
370
  requirements:
335
371
  - - ">="
336
372
  - !ruby/object:Gem::Version
337
- version: '0'
373
+ version: 2.5.0
338
374
  required_rubygems_version: !ruby/object:Gem::Requirement
339
375
  requirements:
340
376
  - - ">="
341
377
  - !ruby/object:Gem::Version
342
378
  version: '0'
343
379
  requirements: []
344
- rubyforge_project:
345
- rubygems_version: 2.5.2.3
380
+ rubygems_version: 3.0.3
346
381
  signing_key:
347
382
  specification_version: 4
348
383
  summary: LaunchDarkly SDK for Ruby
349
384
  test_files:
350
385
  - spec/config_spec.rb
351
386
  - spec/diagnostic_events_spec.rb
352
- - spec/evaluation_spec.rb
387
+ - spec/evaluation_detail_spec.rb
353
388
  - spec/event_sender_spec.rb
354
389
  - spec/event_summarizer_spec.rb
355
390
  - spec/events_spec.rb
@@ -361,6 +396,15 @@ test_files:
361
396
  - spec/fixtures/user.json
362
397
  - spec/flags_state_spec.rb
363
398
  - spec/http_util.rb
399
+ - spec/impl/evaluator_bucketing_spec.rb
400
+ - spec/impl/evaluator_clause_spec.rb
401
+ - spec/impl/evaluator_operators_spec.rb
402
+ - spec/impl/evaluator_rule_spec.rb
403
+ - spec/impl/evaluator_segment_spec.rb
404
+ - spec/impl/evaluator_spec.rb
405
+ - spec/impl/evaluator_spec_base.rb
406
+ - spec/impl/event_factory_spec.rb
407
+ - spec/impl/model/serialization_spec.rb
364
408
  - spec/in_memory_feature_store_spec.rb
365
409
  - spec/integrations/consul_feature_store_spec.rb
366
410
  - spec/integrations/dynamodb_feature_store_spec.rb