launchdarkly-server-sdk 5.7.4 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +5 -5
  2. data/.circleci/config.yml +28 -122
  3. data/.gitignore +1 -1
  4. data/.ldrelease/build-docs.sh +18 -0
  5. data/.ldrelease/circleci/linux/execute.sh +18 -0
  6. data/.ldrelease/circleci/mac/execute.sh +18 -0
  7. data/.ldrelease/circleci/template/build.sh +29 -0
  8. data/.ldrelease/circleci/template/publish.sh +23 -0
  9. data/.ldrelease/circleci/template/set-gem-home.sh +7 -0
  10. data/.ldrelease/circleci/template/test.sh +10 -0
  11. data/.ldrelease/circleci/template/update-version.sh +8 -0
  12. data/.ldrelease/circleci/windows/execute.ps1 +19 -0
  13. data/.ldrelease/config.yml +14 -2
  14. data/CHANGELOG.md +28 -0
  15. data/CONTRIBUTING.md +1 -1
  16. data/Gemfile.lock +92 -76
  17. data/README.md +4 -3
  18. data/azure-pipelines.yml +1 -1
  19. data/docs/Makefile +26 -0
  20. data/docs/index.md +9 -0
  21. data/launchdarkly-server-sdk.gemspec +20 -13
  22. data/lib/ldclient-rb.rb +0 -1
  23. data/lib/ldclient-rb/config.rb +15 -3
  24. data/lib/ldclient-rb/evaluation_detail.rb +293 -0
  25. data/lib/ldclient-rb/events.rb +3 -4
  26. data/lib/ldclient-rb/file_data_source.rb +1 -1
  27. data/lib/ldclient-rb/impl/evaluator.rb +225 -0
  28. data/lib/ldclient-rb/impl/evaluator_bucketing.rb +74 -0
  29. data/lib/ldclient-rb/impl/evaluator_operators.rb +160 -0
  30. data/lib/ldclient-rb/impl/event_factory.rb +22 -0
  31. data/lib/ldclient-rb/impl/event_sender.rb +56 -40
  32. data/lib/ldclient-rb/impl/integrations/consul_impl.rb +5 -5
  33. data/lib/ldclient-rb/impl/integrations/dynamodb_impl.rb +5 -5
  34. data/lib/ldclient-rb/impl/integrations/redis_impl.rb +8 -7
  35. data/lib/ldclient-rb/impl/model/serialization.rb +62 -0
  36. data/lib/ldclient-rb/impl/unbounded_pool.rb +34 -0
  37. data/lib/ldclient-rb/integrations/redis.rb +3 -0
  38. data/lib/ldclient-rb/ldclient.rb +33 -11
  39. data/lib/ldclient-rb/polling.rb +1 -4
  40. data/lib/ldclient-rb/redis_store.rb +1 -0
  41. data/lib/ldclient-rb/requestor.rb +25 -23
  42. data/lib/ldclient-rb/stream.rb +10 -30
  43. data/lib/ldclient-rb/util.rb +12 -8
  44. data/lib/ldclient-rb/version.rb +1 -1
  45. data/spec/evaluation_detail_spec.rb +135 -0
  46. data/spec/event_sender_spec.rb +20 -2
  47. data/spec/events_spec.rb +10 -0
  48. data/spec/http_util.rb +11 -1
  49. data/spec/impl/evaluator_bucketing_spec.rb +111 -0
  50. data/spec/impl/evaluator_clause_spec.rb +55 -0
  51. data/spec/impl/evaluator_operators_spec.rb +141 -0
  52. data/spec/impl/evaluator_rule_spec.rb +96 -0
  53. data/spec/impl/evaluator_segment_spec.rb +125 -0
  54. data/spec/impl/evaluator_spec.rb +305 -0
  55. data/spec/impl/evaluator_spec_base.rb +75 -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 +60 -8
  60. data/spec/polling_spec.rb +2 -2
  61. data/spec/redis_feature_store_spec.rb +32 -3
  62. data/spec/requestor_spec.rb +11 -45
  63. data/spec/spec_helper.rb +0 -3
  64. data/spec/stream_spec.rb +1 -16
  65. metadata +110 -60
  66. data/.yardopts +0 -9
  67. data/lib/ldclient-rb/evaluation.rb +0 -462
  68. data/scripts/gendocs.sh +0 -11
  69. data/scripts/release.sh +0 -27
  70. data/spec/evaluation_spec.rb +0 -789
@@ -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,
@@ -155,6 +161,24 @@ describe LaunchDarkly::LDClient do
155
161
  client.variation("key", nil, "default")
156
162
  end
157
163
 
164
+ it "queues a feature event for an existing feature when user is anonymous" do
165
+ config.feature_store.init({ LaunchDarkly::FEATURES => {} })
166
+ config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
167
+ expect(event_processor).to receive(:add_event).with(hash_including(
168
+ kind: "feature",
169
+ key: "key",
170
+ version: 100,
171
+ contextKind: "anonymousUser",
172
+ user: user_anonymous,
173
+ variation: 0,
174
+ value: "value",
175
+ default: "default",
176
+ trackEvents: true,
177
+ debugEventsUntilDate: 1000
178
+ ))
179
+ client.variation("key", user_anonymous, "default")
180
+ end
181
+
158
182
  it "queues a feature event for an existing feature when user key is nil" do
159
183
  config.feature_store.init({ LaunchDarkly::FEATURES => {} })
160
184
  config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
@@ -197,7 +221,7 @@ describe LaunchDarkly::LDClient do
197
221
  value: 'value',
198
222
  default: 'default',
199
223
  trackEvents: true,
200
- reason: { kind: 'RULE_MATCH', ruleIndex: 0, ruleId: 'id' }
224
+ reason: LaunchDarkly::EvaluationReason::rule_match(0, 'id')
201
225
  ))
202
226
  client.variation('flag', user, 'default')
203
227
  end
@@ -222,7 +246,7 @@ describe LaunchDarkly::LDClient do
222
246
  value: 'value',
223
247
  default: 'default',
224
248
  trackEvents: true,
225
- reason: { kind: 'FALLTHROUGH' }
249
+ reason: LaunchDarkly::EvaluationReason::fallthrough
226
250
  ))
227
251
  client.variation('flag', user, 'default')
228
252
  end
@@ -234,20 +258,22 @@ describe LaunchDarkly::LDClient do
234
258
 
235
259
  it "returns the default value if the client is offline" do
236
260
  result = offline_client.variation_detail("doesntmatter", user, "default")
237
- expected = LaunchDarkly::EvaluationDetail.new("default", nil, { kind: 'ERROR', errorKind: 'CLIENT_NOT_READY' })
261
+ expected = LaunchDarkly::EvaluationDetail.new("default", nil,
262
+ LaunchDarkly::EvaluationReason::error(LaunchDarkly::EvaluationReason::ERROR_CLIENT_NOT_READY))
238
263
  expect(result).to eq expected
239
264
  end
240
265
 
241
266
  it "returns the default value for an unknown feature" do
242
267
  result = client.variation_detail("badkey", user, "default")
243
- expected = LaunchDarkly::EvaluationDetail.new("default", nil, { kind: 'ERROR', errorKind: 'FLAG_NOT_FOUND'})
268
+ expected = LaunchDarkly::EvaluationDetail.new("default", nil,
269
+ LaunchDarkly::EvaluationReason::error(LaunchDarkly::EvaluationReason::ERROR_FLAG_NOT_FOUND))
244
270
  expect(result).to eq expected
245
271
  end
246
272
 
247
273
  it "queues a feature request event for an unknown feature" do
248
274
  expect(event_processor).to receive(:add_event).with(hash_including(
249
275
  kind: "feature", key: "badkey", user: user, value: "default", default: "default",
250
- reason: { kind: 'ERROR', errorKind: 'FLAG_NOT_FOUND' }
276
+ reason: LaunchDarkly::EvaluationReason::error(LaunchDarkly::EvaluationReason::ERROR_FLAG_NOT_FOUND)
251
277
  ))
252
278
  client.variation_detail("badkey", user, "default")
253
279
  end
@@ -256,7 +282,7 @@ describe LaunchDarkly::LDClient do
256
282
  config.feature_store.init({ LaunchDarkly::FEATURES => {} })
257
283
  config.feature_store.upsert(LaunchDarkly::FEATURES, feature_with_value)
258
284
  result = client.variation_detail("key", user, "default")
259
- expected = LaunchDarkly::EvaluationDetail.new("value", 0, { kind: 'OFF' })
285
+ expected = LaunchDarkly::EvaluationDetail.new("value", 0, LaunchDarkly::EvaluationReason::off)
260
286
  expect(result).to eq expected
261
287
  end
262
288
 
@@ -265,7 +291,7 @@ describe LaunchDarkly::LDClient do
265
291
  config.feature_store.init({ LaunchDarkly::FEATURES => {} })
266
292
  config.feature_store.upsert(LaunchDarkly::FEATURES, empty_feature)
267
293
  result = client.variation_detail("key", user, "default")
268
- expected = LaunchDarkly::EvaluationDetail.new("default", nil, { kind: 'OFF' })
294
+ expected = LaunchDarkly::EvaluationDetail.new("default", nil, LaunchDarkly::EvaluationReason::off)
269
295
  expect(result).to eq expected
270
296
  expect(result.default_value?).to be true
271
297
  end
@@ -283,7 +309,7 @@ describe LaunchDarkly::LDClient do
283
309
  default: "default",
284
310
  trackEvents: true,
285
311
  debugEventsUntilDate: 1000,
286
- reason: { kind: "OFF" }
312
+ reason: LaunchDarkly::EvaluationReason::off
287
313
  ))
288
314
  client.variation_detail("key", user, "default")
289
315
  end
@@ -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,4 +1,5 @@
1
1
  require "feature_store_spec_base"
2
+ require "connection_pool"
2
3
  require "json"
3
4
  require "redis"
4
5
  require "spec_helper"
@@ -31,7 +32,7 @@ describe LaunchDarkly::RedisFeatureStore do
31
32
  break if ENV['LD_SKIP_DATABASE_TESTS'] == '1'
32
33
 
33
34
  # These tests will all fail if there isn't a Redis instance running on the default port.
34
-
35
+
35
36
  context "real Redis with local cache" do
36
37
  include_examples "feature_store", method(:create_redis_store), method(:clear_all_data)
37
38
  end
@@ -59,7 +60,7 @@ describe LaunchDarkly::RedisFeatureStore do
59
60
  flag = { key: "foo", version: 1 }
60
61
  test_hook = make_concurrent_modifier_test_hook(other_client, flag, 2, 4)
61
62
  store = create_redis_store({ test_hook: test_hook })
62
-
63
+
63
64
  begin
64
65
  store.init(LaunchDarkly::FEATURES => { flag[:key] => flag })
65
66
 
@@ -77,7 +78,7 @@ describe LaunchDarkly::RedisFeatureStore do
77
78
  flag = { key: "foo", version: 1 }
78
79
  test_hook = make_concurrent_modifier_test_hook(other_client, flag, 3, 3)
79
80
  store = create_redis_store({ test_hook: test_hook })
80
-
81
+
81
82
  begin
82
83
  store.init(LaunchDarkly::FEATURES => { flag[:key] => flag })
83
84
 
@@ -89,4 +90,32 @@ describe LaunchDarkly::RedisFeatureStore do
89
90
  other_client.close
90
91
  end
91
92
  end
93
+
94
+ it "shuts down a custom Redis pool by default" do
95
+ unowned_pool = ConnectionPool.new(size: 1, timeout: 1) { Redis.new({ url: "redis://localhost:6379" }) }
96
+ store = create_redis_store({ pool: unowned_pool })
97
+
98
+ begin
99
+ store.init(LaunchDarkly::FEATURES => { })
100
+ store.stop
101
+
102
+ expect { unowned_pool.with {} }.to raise_error(ConnectionPool::PoolShuttingDownError)
103
+ ensure
104
+ unowned_pool.shutdown { |conn| conn.close }
105
+ end
106
+ end
107
+
108
+ it "doesn't shut down a custom Redis pool if pool_shutdown_on_close = false" do
109
+ unowned_pool = ConnectionPool.new(size: 1, timeout: 1) { Redis.new({ url: "redis://localhost:6379" }) }
110
+ store = create_redis_store({ pool: unowned_pool, pool_shutdown_on_close: false })
111
+
112
+ begin
113
+ store.init(LaunchDarkly::FEATURES => { })
114
+ store.stop
115
+
116
+ expect { unowned_pool.with {} }.not_to raise_error(ConnectionPool::PoolShuttingDownError)
117
+ ensure
118
+ unowned_pool.shutdown { |conn| conn.close }
119
+ end
120
+ end
92
121
  end
@@ -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
@@ -193,38 +193,4 @@ describe LaunchDarkly::Requestor do
193
193
  end
194
194
  end
195
195
  end
196
-
197
- describe "request_flag" do
198
- it "uses expected URI and headers" do
199
- with_server do |server|
200
- with_requestor(server.base_uri.to_s) do |requestor|
201
- server.setup_ok_response("/", "{}")
202
- requestor.request_flag("key")
203
- expect(server.requests.count).to eq 1
204
- expect(server.requests[0].unparsed_uri).to eq "/sdk/latest-flags/key"
205
- expect(server.requests[0].header).to include({
206
- "authorization" => [ $sdk_key ],
207
- "user-agent" => [ "RubyClient/" + LaunchDarkly::VERSION ]
208
- })
209
- end
210
- end
211
- end
212
- end
213
-
214
- describe "request_segment" do
215
- it "uses expected URI and headers" do
216
- with_server do |server|
217
- with_requestor(server.base_uri.to_s) do |requestor|
218
- server.setup_ok_response("/", "{}")
219
- requestor.request_segment("key")
220
- expect(server.requests.count).to eq 1
221
- expect(server.requests[0].unparsed_uri).to eq "/sdk/latest-segments/key"
222
- expect(server.requests[0].header).to include({
223
- "authorization" => [ $sdk_key ],
224
- "user-agent" => [ "RubyClient/" + LaunchDarkly::VERSION ]
225
- })
226
- end
227
- end
228
- end
229
- end
230
196
  end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,3 @@
1
- require "codeclimate-test-reporter"
2
- CodeClimate::TestReporter.start
3
-
4
1
  require "ldclient-rb"
5
2
 
6
3
  $null_log = ::Logger.new($stdout)
data/spec/stream_spec.rb CHANGED
@@ -4,8 +4,7 @@ require "spec_helper"
4
4
  describe LaunchDarkly::StreamProcessor do
5
5
  subject { LaunchDarkly::StreamProcessor }
6
6
  let(:config) { LaunchDarkly::Config.new }
7
- let(:requestor) { double() }
8
- let(:processor) { subject.new("sdk_key", config, requestor) }
7
+ let(:processor) { subject.new("sdk_key", config) }
9
8
 
10
9
  describe '#process_message' do
11
10
  let(:put_message) { SSE::StreamEvent.new(:put, '{"data":{"flags":{"asdf": {"key": "asdf"}},"segments":{"segkey": {"key": "segkey"}}}}') }
@@ -13,8 +12,6 @@ describe LaunchDarkly::StreamProcessor do
13
12
  let(:patch_seg_message) { SSE::StreamEvent.new(:patch, '{"path": "/segments/key", "data": {"key": "asdf", "version": 1}}') }
14
13
  let(:delete_flag_message) { SSE::StreamEvent.new(:delete, '{"path": "/flags/key", "version": 2}') }
15
14
  let(:delete_seg_message) { SSE::StreamEvent.new(:delete, '{"path": "/segments/key", "version": 2}') }
16
- let(:indirect_patch_flag_message) { SSE::StreamEvent.new(:'indirect/patch', "/flags/key") }
17
- let(:indirect_patch_segment_message) { SSE::StreamEvent.new(:'indirect/patch', "/segments/key") }
18
15
 
19
16
  it "will accept PUT methods" do
20
17
  processor.send(:process_message, put_message)
@@ -39,18 +36,6 @@ describe LaunchDarkly::StreamProcessor do
39
36
  processor.send(:process_message, delete_seg_message)
40
37
  expect(config.feature_store.get(LaunchDarkly::SEGMENTS, "key")).to eq(nil)
41
38
  end
42
- it "will accept INDIRECT PATCH method for flags" do
43
- flag = { key: 'key', version: 1 }
44
- allow(requestor).to receive(:request_flag).with(flag[:key]).and_return(flag)
45
- processor.send(:process_message, indirect_patch_flag_message);
46
- expect(config.feature_store.get(LaunchDarkly::FEATURES, flag[:key])).to eq(flag)
47
- end
48
- it "will accept INDIRECT PATCH method for segments" do
49
- segment = { key: 'key', version: 1 }
50
- allow(requestor).to receive(:request_segment).with(segment[:key]).and_return(segment)
51
- processor.send(:process_message, indirect_patch_segment_message);
52
- expect(config.feature_store.get(LaunchDarkly::SEGMENTS, segment[:key])).to eq(segment)
53
- end
54
39
  it "will log a warning if the method is not recognized" do
55
40
  expect(processor.instance_variable_get(:@config).logger).to receive :warn
56
41
  processor.send(:process_message, SSE::StreamEvent.new(type: :get, data: "", id: 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.7.4
4
+ version: 6.1.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-05-04 00:00:00.000000000 Z
11
+ date: 2021-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-dynamodb
@@ -16,160 +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.7'
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.7'
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
- name: codeclimate-test-reporter
56
+ name: diplomat
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
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: '0'
68
+ version: 2.4.2
69
69
  - !ruby/object:Gem::Dependency
70
- name: diplomat
70
+ name: redis
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: 2.0.2
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: 2.0.2
82
+ version: '4.2'
83
83
  - !ruby/object:Gem::Dependency
84
- name: redis
84
+ name: connection_pool
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 3.3.5
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: 3.3.5
96
+ version: 2.2.3
97
97
  - !ruby/object:Gem::Dependency
98
- name: connection_pool
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: 2.1.2
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: 2.1.2
110
+ version: '0.4'
111
111
  - !ruby/object:Gem::Dependency
112
- name: rspec_junit_formatter
112
+ name: timecop
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
115
  - - "~>"
116
116
  - !ruby/object:Gem::Version
117
- version: 0.3.0
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.3.0
124
+ version: '0.9'
125
125
  - !ruby/object:Gem::Dependency
126
- name: timecop
126
+ name: listen
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
129
  - - "~>"
130
130
  - !ruby/object:Gem::Version
131
- version: 0.9.1
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: 0.9.1
138
+ version: '3.3'
139
139
  - !ruby/object:Gem::Dependency
140
- name: listen
140
+ name: webrick
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: '3.0'
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: '3.0'
152
+ version: '1.7'
153
153
  - !ruby/object:Gem::Dependency
154
- name: json
154
+ name: oga
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - ">="
158
- - !ruby/object:Gem::Version
159
- version: '1.8'
160
- - - "<"
157
+ - - "~>"
161
158
  - !ruby/object:Gem::Version
162
- version: '3'
163
- type: :runtime
159
+ version: '2.2'
160
+ type: :development
164
161
  prerelease: false
165
162
  version_requirements: !ruby/object:Gem::Requirement
166
163
  requirements:
167
- - - ">="
168
- - !ruby/object:Gem::Version
169
- version: '1.8'
170
- - - "<"
164
+ - - "~>"
171
165
  - !ruby/object:Gem::Version
172
- version: '3'
166
+ version: '2.2'
173
167
  - !ruby/object:Gem::Dependency
174
168
  name: semantic
175
169
  requirement: !ruby/object:Gem::Requirement
@@ -190,28 +184,56 @@ dependencies:
190
184
  requirements:
191
185
  - - "~>"
192
186
  - !ruby/object:Gem::Version
193
- version: '1.0'
187
+ version: '1.1'
194
188
  type: :runtime
195
189
  prerelease: false
196
190
  version_requirements: !ruby/object:Gem::Requirement
197
191
  requirements:
198
192
  - - "~>"
199
193
  - !ruby/object:Gem::Version
200
- version: '1.0'
194
+ version: '1.1'
201
195
  - !ruby/object:Gem::Dependency
202
196
  name: ld-eventsource
203
197
  requirement: !ruby/object:Gem::Requirement
204
198
  requirements:
205
- - - '='
199
+ - - "~>"
200
+ - !ruby/object:Gem::Version
201
+ version: '2.0'
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - "~>"
207
+ - !ruby/object:Gem::Version
208
+ version: '2.0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: json
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - "~>"
206
214
  - !ruby/object:Gem::Version
207
- version: 1.0.3
215
+ version: 2.3.1
208
216
  type: :runtime
209
217
  prerelease: false
210
218
  version_requirements: !ruby/object:Gem::Requirement
211
219
  requirements:
212
- - - '='
220
+ - - "~>"
213
221
  - !ruby/object:Gem::Version
214
- version: 1.0.3
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
215
237
  description: Official LaunchDarkly SDK for Ruby
216
238
  email:
217
239
  - team@launchdarkly.com
@@ -225,11 +247,19 @@ files:
225
247
  - ".github/pull_request_template.md"
226
248
  - ".gitignore"
227
249
  - ".hound.yml"
250
+ - ".ldrelease/build-docs.sh"
251
+ - ".ldrelease/circleci/linux/execute.sh"
252
+ - ".ldrelease/circleci/mac/execute.sh"
253
+ - ".ldrelease/circleci/template/build.sh"
254
+ - ".ldrelease/circleci/template/publish.sh"
255
+ - ".ldrelease/circleci/template/set-gem-home.sh"
256
+ - ".ldrelease/circleci/template/test.sh"
257
+ - ".ldrelease/circleci/template/update-version.sh"
258
+ - ".ldrelease/circleci/windows/execute.ps1"
228
259
  - ".ldrelease/config.yml"
229
260
  - ".rspec"
230
261
  - ".rubocop.yml"
231
262
  - ".simplecov"
232
- - ".yardopts"
233
263
  - CHANGELOG.md
234
264
  - CODEOWNERS
235
265
  - CONTRIBUTING.md
@@ -238,12 +268,14 @@ files:
238
268
  - LICENSE.txt
239
269
  - README.md
240
270
  - azure-pipelines.yml
271
+ - docs/Makefile
272
+ - docs/index.md
241
273
  - launchdarkly-server-sdk.gemspec
242
274
  - lib/launchdarkly-server-sdk.rb
243
275
  - lib/ldclient-rb.rb
244
276
  - lib/ldclient-rb/cache_store.rb
245
277
  - lib/ldclient-rb/config.rb
246
- - lib/ldclient-rb/evaluation.rb
278
+ - lib/ldclient-rb/evaluation_detail.rb
247
279
  - lib/ldclient-rb/event_summarizer.rb
248
280
  - lib/ldclient-rb/events.rb
249
281
  - lib/ldclient-rb/expiring_cache.rb
@@ -251,13 +283,18 @@ files:
251
283
  - lib/ldclient-rb/flags_state.rb
252
284
  - lib/ldclient-rb/impl.rb
253
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
254
289
  - lib/ldclient-rb/impl/event_factory.rb
255
290
  - lib/ldclient-rb/impl/event_sender.rb
256
291
  - lib/ldclient-rb/impl/integrations/consul_impl.rb
257
292
  - lib/ldclient-rb/impl/integrations/dynamodb_impl.rb
258
293
  - lib/ldclient-rb/impl/integrations/redis_impl.rb
294
+ - lib/ldclient-rb/impl/model/serialization.rb
259
295
  - lib/ldclient-rb/impl/store_client_wrapper.rb
260
296
  - lib/ldclient-rb/impl/store_data_set_sorter.rb
297
+ - lib/ldclient-rb/impl/unbounded_pool.rb
261
298
  - lib/ldclient-rb/impl/util.rb
262
299
  - lib/ldclient-rb/in_memory_store.rb
263
300
  - lib/ldclient-rb/integrations.rb
@@ -278,11 +315,9 @@ files:
278
315
  - lib/ldclient-rb/user_filter.rb
279
316
  - lib/ldclient-rb/util.rb
280
317
  - lib/ldclient-rb/version.rb
281
- - scripts/gendocs.sh
282
- - scripts/release.sh
283
318
  - spec/config_spec.rb
284
319
  - spec/diagnostic_events_spec.rb
285
- - spec/evaluation_spec.rb
320
+ - spec/evaluation_detail_spec.rb
286
321
  - spec/event_sender_spec.rb
287
322
  - spec/event_summarizer_spec.rb
288
323
  - spec/events_spec.rb
@@ -294,6 +329,14 @@ files:
294
329
  - spec/fixtures/user.json
295
330
  - spec/flags_state_spec.rb
296
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/model/serialization_spec.rb
297
340
  - spec/in_memory_feature_store_spec.rb
298
341
  - spec/integrations/consul_feature_store_spec.rb
299
342
  - spec/integrations/dynamodb_feature_store_spec.rb
@@ -326,22 +369,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
326
369
  requirements:
327
370
  - - ">="
328
371
  - !ruby/object:Gem::Version
329
- version: '0'
372
+ version: 2.5.0
330
373
  required_rubygems_version: !ruby/object:Gem::Requirement
331
374
  requirements:
332
375
  - - ">="
333
376
  - !ruby/object:Gem::Version
334
377
  version: '0'
335
378
  requirements: []
336
- rubyforge_project:
337
- rubygems_version: 2.5.2.3
379
+ rubygems_version: 3.0.3
338
380
  signing_key:
339
381
  specification_version: 4
340
382
  summary: LaunchDarkly SDK for Ruby
341
383
  test_files:
342
384
  - spec/config_spec.rb
343
385
  - spec/diagnostic_events_spec.rb
344
- - spec/evaluation_spec.rb
386
+ - spec/evaluation_detail_spec.rb
345
387
  - spec/event_sender_spec.rb
346
388
  - spec/event_summarizer_spec.rb
347
389
  - spec/events_spec.rb
@@ -353,6 +395,14 @@ test_files:
353
395
  - spec/fixtures/user.json
354
396
  - spec/flags_state_spec.rb
355
397
  - spec/http_util.rb
398
+ - spec/impl/evaluator_bucketing_spec.rb
399
+ - spec/impl/evaluator_clause_spec.rb
400
+ - spec/impl/evaluator_operators_spec.rb
401
+ - spec/impl/evaluator_rule_spec.rb
402
+ - spec/impl/evaluator_segment_spec.rb
403
+ - spec/impl/evaluator_spec.rb
404
+ - spec/impl/evaluator_spec_base.rb
405
+ - spec/impl/model/serialization_spec.rb
356
406
  - spec/in_memory_feature_store_spec.rb
357
407
  - spec/integrations/consul_feature_store_spec.rb
358
408
  - spec/integrations/dynamodb_feature_store_spec.rb