launchdarkly-server-sdk 6.2.3 → 6.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/lib/ldclient-rb/config.rb +81 -4
  4. data/lib/ldclient-rb/evaluation_detail.rb +67 -8
  5. data/lib/ldclient-rb/file_data_source.rb +9 -300
  6. data/lib/ldclient-rb/impl/big_segments.rb +117 -0
  7. data/lib/ldclient-rb/impl/evaluator.rb +80 -28
  8. data/lib/ldclient-rb/impl/integrations/dynamodb_impl.rb +82 -18
  9. data/lib/ldclient-rb/impl/integrations/file_data_source.rb +212 -0
  10. data/lib/ldclient-rb/impl/integrations/redis_impl.rb +84 -31
  11. data/lib/ldclient-rb/impl/integrations/test_data/test_data_source.rb +40 -0
  12. data/lib/ldclient-rb/impl/repeating_task.rb +47 -0
  13. data/lib/ldclient-rb/impl/util.rb +4 -1
  14. data/lib/ldclient-rb/integrations/consul.rb +7 -0
  15. data/lib/ldclient-rb/integrations/dynamodb.rb +47 -2
  16. data/lib/ldclient-rb/integrations/file_data.rb +108 -0
  17. data/lib/ldclient-rb/integrations/redis.rb +41 -1
  18. data/lib/ldclient-rb/integrations/test_data/flag_builder.rb +438 -0
  19. data/lib/ldclient-rb/integrations/test_data.rb +209 -0
  20. data/lib/ldclient-rb/integrations/util/store_wrapper.rb +5 -0
  21. data/lib/ldclient-rb/integrations.rb +2 -51
  22. data/lib/ldclient-rb/interfaces.rb +152 -2
  23. data/lib/ldclient-rb/ldclient.rb +21 -7
  24. data/lib/ldclient-rb/polling.rb +22 -41
  25. data/lib/ldclient-rb/util.rb +1 -1
  26. data/lib/ldclient-rb/version.rb +1 -1
  27. metadata +31 -132
  28. data/.circleci/config.yml +0 -40
  29. data/.github/ISSUE_TEMPLATE/bug_report.md +0 -37
  30. data/.github/ISSUE_TEMPLATE/config.yml +0 -5
  31. data/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  32. data/.github/pull_request_template.md +0 -21
  33. data/.gitignore +0 -16
  34. data/.hound.yml +0 -2
  35. data/.ldrelease/build-docs.sh +0 -18
  36. data/.ldrelease/circleci/linux/execute.sh +0 -18
  37. data/.ldrelease/circleci/mac/execute.sh +0 -18
  38. data/.ldrelease/circleci/template/build.sh +0 -29
  39. data/.ldrelease/circleci/template/publish.sh +0 -23
  40. data/.ldrelease/circleci/template/set-gem-home.sh +0 -7
  41. data/.ldrelease/circleci/template/test.sh +0 -10
  42. data/.ldrelease/circleci/template/update-version.sh +0 -8
  43. data/.ldrelease/circleci/windows/execute.ps1 +0 -19
  44. data/.ldrelease/config.yml +0 -29
  45. data/.rspec +0 -2
  46. data/.rubocop.yml +0 -600
  47. data/.simplecov +0 -4
  48. data/CHANGELOG.md +0 -367
  49. data/CODEOWNERS +0 -1
  50. data/CONTRIBUTING.md +0 -37
  51. data/Gemfile +0 -3
  52. data/azure-pipelines.yml +0 -51
  53. data/docs/Makefile +0 -26
  54. data/docs/index.md +0 -9
  55. data/launchdarkly-server-sdk.gemspec +0 -45
  56. data/spec/config_spec.rb +0 -63
  57. data/spec/diagnostic_events_spec.rb +0 -165
  58. data/spec/evaluation_detail_spec.rb +0 -135
  59. data/spec/event_sender_spec.rb +0 -197
  60. data/spec/event_summarizer_spec.rb +0 -63
  61. data/spec/events_spec.rb +0 -607
  62. data/spec/expiring_cache_spec.rb +0 -76
  63. data/spec/feature_store_spec_base.rb +0 -213
  64. data/spec/file_data_source_spec.rb +0 -283
  65. data/spec/fixtures/feature.json +0 -37
  66. data/spec/fixtures/feature1.json +0 -36
  67. data/spec/fixtures/user.json +0 -9
  68. data/spec/flags_state_spec.rb +0 -81
  69. data/spec/http_util.rb +0 -132
  70. data/spec/impl/evaluator_bucketing_spec.rb +0 -216
  71. data/spec/impl/evaluator_clause_spec.rb +0 -55
  72. data/spec/impl/evaluator_operators_spec.rb +0 -141
  73. data/spec/impl/evaluator_rule_spec.rb +0 -128
  74. data/spec/impl/evaluator_segment_spec.rb +0 -125
  75. data/spec/impl/evaluator_spec.rb +0 -349
  76. data/spec/impl/evaluator_spec_base.rb +0 -75
  77. data/spec/impl/event_factory_spec.rb +0 -108
  78. data/spec/impl/model/serialization_spec.rb +0 -41
  79. data/spec/in_memory_feature_store_spec.rb +0 -12
  80. data/spec/integrations/consul_feature_store_spec.rb +0 -40
  81. data/spec/integrations/dynamodb_feature_store_spec.rb +0 -103
  82. data/spec/integrations/store_wrapper_spec.rb +0 -276
  83. data/spec/launchdarkly-server-sdk_spec.rb +0 -13
  84. data/spec/launchdarkly-server-sdk_spec_autoloadtest.rb +0 -9
  85. data/spec/ldclient_end_to_end_spec.rb +0 -157
  86. data/spec/ldclient_spec.rb +0 -635
  87. data/spec/newrelic_spec.rb +0 -5
  88. data/spec/polling_spec.rb +0 -120
  89. data/spec/redis_feature_store_spec.rb +0 -121
  90. data/spec/requestor_spec.rb +0 -209
  91. data/spec/segment_store_spec_base.rb +0 -95
  92. data/spec/simple_lru_cache_spec.rb +0 -24
  93. data/spec/spec_helper.rb +0 -9
  94. data/spec/store_spec.rb +0 -10
  95. data/spec/stream_spec.rb +0 -45
  96. data/spec/user_filter_spec.rb +0 -91
  97. data/spec/util_spec.rb +0 -17
  98. data/spec/version_spec.rb +0 -7
@@ -1,165 +0,0 @@
1
- require "ldclient-rb/impl/diagnostic_events"
2
-
3
- require "spec_helper"
4
-
5
- module LaunchDarkly
6
- module Impl
7
- describe DiagnosticAccumulator do
8
- subject { DiagnosticAccumulator }
9
-
10
- let(:sdk_key) { "sdk_key" }
11
- let(:default_id) { subject.create_diagnostic_id("my-key") }
12
- let(:default_acc) { subject.new(default_id) }
13
-
14
- it "creates unique ID with SDK key suffix" do
15
- id1 = subject.create_diagnostic_id("1234567890")
16
- expect(id1[:sdkKeySuffix]).to eq "567890"
17
- expect(id1[:diagnosticId]).not_to be_nil
18
-
19
- id2 = subject.create_diagnostic_id("1234567890")
20
- expect(id2[:diagnosticId]).not_to eq id1[:diagnosticId]
21
- end
22
-
23
- describe "init event" do
24
- def expected_default_config
25
- {
26
- allAttributesPrivate: false,
27
- connectTimeoutMillis: Config.default_connect_timeout * 1000,
28
- customBaseURI: false,
29
- customEventsURI: false,
30
- customStreamURI: false,
31
- diagnosticRecordingIntervalMillis: Config.default_diagnostic_recording_interval * 1000,
32
- eventsCapacity: Config.default_capacity,
33
- eventsFlushIntervalMillis: Config.default_flush_interval * 1000,
34
- inlineUsersInEvents: false,
35
- pollingIntervalMillis: Config.default_poll_interval * 1000,
36
- socketTimeoutMillis: Config.default_read_timeout * 1000,
37
- streamingDisabled: false,
38
- userKeysCapacity: Config.default_user_keys_capacity,
39
- userKeysFlushIntervalMillis: Config.default_user_keys_flush_interval * 1000,
40
- usingProxy: false,
41
- usingRelayDaemon: false
42
- }
43
- end
44
-
45
- it "has basic fields" do
46
- event = default_acc.create_init_event(Config.new)
47
- expect(event[:kind]).to eq 'diagnostic-init'
48
- expect(event[:creationDate]).not_to be_nil
49
- expect(event[:id]).to eq default_id
50
- end
51
-
52
- it "can have default config data" do
53
- event = default_acc.create_init_event(Config.new)
54
- expect(event[:configuration]).to eq expected_default_config
55
- end
56
-
57
- it "can have custom config data" do
58
- changes_and_expected = [
59
- [ { all_attributes_private: true }, { allAttributesPrivate: true } ],
60
- [ { connect_timeout: 46 }, { connectTimeoutMillis: 46000 } ],
61
- [ { base_uri: 'http://custom' }, { customBaseURI: true } ],
62
- [ { events_uri: 'http://custom' }, { customEventsURI: true } ],
63
- [ { stream_uri: 'http://custom' }, { customStreamURI: true } ],
64
- [ { diagnostic_recording_interval: 9999 }, { diagnosticRecordingIntervalMillis: 9999000 } ],
65
- [ { capacity: 4000 }, { eventsCapacity: 4000 } ],
66
- [ { flush_interval: 46 }, { eventsFlushIntervalMillis: 46000 } ],
67
- [ { inline_users_in_events: true }, { inlineUsersInEvents: true } ],
68
- [ { poll_interval: 999 }, { pollingIntervalMillis: 999000 } ],
69
- [ { read_timeout: 46 }, { socketTimeoutMillis: 46000 } ],
70
- [ { stream: false }, { streamingDisabled: true } ],
71
- [ { user_keys_capacity: 999 }, { userKeysCapacity: 999 } ],
72
- [ { user_keys_flush_interval: 999 }, { userKeysFlushIntervalMillis: 999000 } ],
73
- [ { use_ldd: true }, { usingRelayDaemon: true } ]
74
- ]
75
- changes_and_expected.each do |config_values, expected_values|
76
- config = Config.new(config_values)
77
- event = default_acc.create_init_event(config)
78
- expect(event[:configuration]).to eq expected_default_config.merge(expected_values)
79
- end
80
- end
81
-
82
- ['http_proxy', 'https_proxy', 'HTTP_PROXY', 'HTTPS_PROXY'].each do |name|
83
- it "detects proxy #{name}" do
84
- begin
85
- ENV[name] = 'http://my-proxy'
86
- event = default_acc.create_init_event(Config.new)
87
- expect(event[:configuration][:usingProxy]).to be true
88
- ensure
89
- ENV[name] = nil
90
- end
91
- end
92
- end
93
-
94
- it "has expected SDK data" do
95
- event = default_acc.create_init_event(Config.new)
96
- expect(event[:sdk]).to eq ({
97
- name: 'ruby-server-sdk',
98
- version: LaunchDarkly::VERSION
99
- })
100
- end
101
-
102
- it "has expected SDK data with wrapper" do
103
- event = default_acc.create_init_event(Config.new(wrapper_name: 'my-wrapper', wrapper_version: '2.0'))
104
- expect(event[:sdk]).to eq ({
105
- name: 'ruby-server-sdk',
106
- version: LaunchDarkly::VERSION,
107
- wrapperName: 'my-wrapper',
108
- wrapperVersion: '2.0'
109
- })
110
- end
111
-
112
- it "has expected platform data" do
113
- event = default_acc.create_init_event(Config.new)
114
- expect(event[:platform]).to include ({
115
- name: 'ruby'
116
- })
117
- end
118
- end
119
-
120
- describe "periodic event" do
121
- it "has correct default values" do
122
- acc = subject.new(default_id)
123
- event = acc.create_periodic_event_and_reset(2, 3, 4)
124
- expect(event).to include({
125
- kind: 'diagnostic',
126
- id: default_id,
127
- droppedEvents: 2,
128
- deduplicatedUsers: 3,
129
- eventsInLastBatch: 4,
130
- streamInits: []
131
- })
132
- expect(event[:creationDate]).not_to be_nil
133
- expect(event[:dataSinceDate]).not_to be_nil
134
- end
135
-
136
- it "can add stream init" do
137
- acc = subject.new(default_id)
138
- acc.record_stream_init(1000, false, 2000)
139
- event = acc.create_periodic_event_and_reset(0, 0, 0)
140
- expect(event[:streamInits]).to eq [{ timestamp: 1000, failed: false, durationMillis: 2000 }]
141
- end
142
-
143
- it "resets fields after creating event" do
144
- acc = subject.new(default_id)
145
- acc.record_stream_init(1000, false, 2000)
146
- event1 = acc.create_periodic_event_and_reset(2, 3, 4)
147
- event2 = acc.create_periodic_event_and_reset(5, 6, 7)
148
- expect(event1).to include ({
149
- droppedEvents: 2,
150
- deduplicatedUsers: 3,
151
- eventsInLastBatch: 4,
152
- streamInits: [{ timestamp: 1000, failed: false, durationMillis: 2000 }]
153
- })
154
- expect(event2).to include ({
155
- dataSinceDate: event1[:creationDate],
156
- droppedEvents: 5,
157
- deduplicatedUsers: 6,
158
- eventsInLastBatch: 7,
159
- streamInits: []
160
- })
161
- end
162
- end
163
- end
164
- end
165
- end
@@ -1,135 +0,0 @@
1
- require "spec_helper"
2
-
3
- module LaunchDarkly
4
- describe "EvaluationDetail" do
5
- subject { EvaluationDetail }
6
-
7
- it "sets properties" do
8
- expect(EvaluationDetail.new("x", 0, EvaluationReason::off).value).to eq "x"
9
- expect(EvaluationDetail.new("x", 0, EvaluationReason::off).variation_index).to eq 0
10
- expect(EvaluationDetail.new("x", 0, EvaluationReason::off).reason).to eq EvaluationReason::off
11
- end
12
-
13
- it "checks parameter types" do
14
- expect { EvaluationDetail.new(nil, nil, EvaluationReason::off) }.not_to raise_error
15
- expect { EvaluationDetail.new(nil, 0, EvaluationReason::off) }.not_to raise_error
16
- expect { EvaluationDetail.new(nil, "x", EvaluationReason::off) }.to raise_error(ArgumentError)
17
- expect { EvaluationDetail.new(nil, 0, { kind: "OFF" }) }.to raise_error(ArgumentError)
18
- expect { EvaluationDetail.new(nil, 0, nil) }.to raise_error(ArgumentError)
19
- end
20
-
21
- it "equality test" do
22
- expect(EvaluationDetail.new("x", 0, EvaluationReason::off)).to eq EvaluationDetail.new("x", 0, EvaluationReason::off)
23
- expect(EvaluationDetail.new("x", 0, EvaluationReason::off)).not_to eq EvaluationDetail.new("y", 0, EvaluationReason::off)
24
- expect(EvaluationDetail.new("x", 0, EvaluationReason::off)).not_to eq EvaluationDetail.new("x", 1, EvaluationReason::off)
25
- expect(EvaluationDetail.new("x", 0, EvaluationReason::off)).not_to eq EvaluationDetail.new("x", 0, EvaluationReason::fallthrough)
26
- end
27
- end
28
-
29
- describe "EvaluationReason" do
30
- subject { EvaluationReason }
31
-
32
- values = [
33
- [ EvaluationReason::off, EvaluationReason::OFF, { "kind" => "OFF" }, "OFF", nil ],
34
- [ EvaluationReason::fallthrough, EvaluationReason::FALLTHROUGH,
35
- { "kind" => "FALLTHROUGH" }, "FALLTHROUGH", nil ],
36
- [ EvaluationReason::target_match, EvaluationReason::TARGET_MATCH,
37
- { "kind" => "TARGET_MATCH" }, "TARGET_MATCH", nil ],
38
- [ EvaluationReason::rule_match(1, "x"), EvaluationReason::RULE_MATCH,
39
- { "kind" => "RULE_MATCH", "ruleIndex" => 1, "ruleId" => "x" }, "RULE_MATCH(1,x)",
40
- [ EvaluationReason::rule_match(2, "x"), EvaluationReason::rule_match(1, "y") ] ],
41
- [ EvaluationReason::prerequisite_failed("x"), EvaluationReason::PREREQUISITE_FAILED,
42
- { "kind" => "PREREQUISITE_FAILED", "prerequisiteKey" => "x" }, "PREREQUISITE_FAILED(x)" ],
43
- [ EvaluationReason::error(EvaluationReason::ERROR_FLAG_NOT_FOUND), EvaluationReason::ERROR,
44
- { "kind" => "ERROR", "errorKind" => "FLAG_NOT_FOUND" }, "ERROR(FLAG_NOT_FOUND)" ]
45
- ]
46
- values.each_index do |i|
47
- params = values[i]
48
- reason = params[0]
49
- kind = params[1]
50
- json_rep = params[2]
51
- brief_str = params[3]
52
- unequal_values = params[4]
53
-
54
- describe "reason #{reason.kind}" do
55
- it "has correct kind" do
56
- expect(reason.kind).to eq kind
57
- end
58
-
59
- it "equality to self" do
60
- expect(reason).to eq reason
61
- end
62
-
63
- it "inequality to others" do
64
- values.each_index do |j|
65
- if i != j
66
- expect(reason).not_to eq values[j][0]
67
- end
68
- end
69
- if !unequal_values.nil?
70
- unequal_values.each do |v|
71
- expect(reason).not_to eq v
72
- end
73
- end
74
- end
75
-
76
- it "JSON representation" do
77
- expect(JSON.parse(reason.as_json.to_json)).to eq json_rep
78
- expect(JSON.parse(reason.to_json)).to eq json_rep
79
- end
80
-
81
- it "brief representation" do
82
- expect(reason.inspect).to eq brief_str
83
- expect(reason.to_s).to eq brief_str
84
- end
85
- end
86
- end
87
-
88
- it "reuses singleton reasons" do
89
- expect(EvaluationReason::off).to be EvaluationReason::off
90
- expect(EvaluationReason::fallthrough).to be EvaluationReason::fallthrough
91
- expect(EvaluationReason::target_match).to be EvaluationReason::target_match
92
- expect(EvaluationReason::rule_match(1, 'x')).not_to be EvaluationReason::rule_match(1, 'x')
93
- expect(EvaluationReason::prerequisite_failed('x')).not_to be EvaluationReason::prerequisite_failed('x')
94
- errors = [ EvaluationReason::ERROR_CLIENT_NOT_READY, EvaluationReason::ERROR_FLAG_NOT_FOUND,
95
- EvaluationReason::ERROR_MALFORMED_FLAG, EvaluationReason::ERROR_USER_NOT_SPECIFIED, EvaluationReason::ERROR_EXCEPTION ]
96
- errors.each do |e|
97
- expect(EvaluationReason::error(e)).to be EvaluationReason::error(e)
98
- end
99
- end
100
-
101
- it "supports [] with JSON property names" do
102
- expect(EvaluationReason::off[:kind]).to eq "OFF"
103
- expect(EvaluationReason::off[:ruleIndex]).to be nil
104
- expect(EvaluationReason::off[:ruleId]).to be nil
105
- expect(EvaluationReason::off[:prerequisiteKey]).to be nil
106
- expect(EvaluationReason::off[:errorKind]).to be nil
107
- expect(EvaluationReason::rule_match(1, "x")[:ruleIndex]).to eq 1
108
- expect(EvaluationReason::rule_match(1, "x")[:ruleId]).to eq "x"
109
- expect(EvaluationReason::prerequisite_failed("x")[:prerequisiteKey]).to eq "x"
110
- expect(EvaluationReason::error(EvaluationReason::ERROR_FLAG_NOT_FOUND)[:errorKind]).to eq "FLAG_NOT_FOUND"
111
- end
112
-
113
- it "freezes string properties" do
114
- rm = EvaluationReason::rule_match(1, "x")
115
- expect { rm.rule_id.upcase! }.to raise_error(RuntimeError)
116
- pf = EvaluationReason::prerequisite_failed("x")
117
- expect { pf.prerequisite_key.upcase! }.to raise_error(RuntimeError)
118
- end
119
-
120
- it "checks parameter types" do
121
- expect { EvaluationReason::rule_match(nil, "x") }.to raise_error(ArgumentError)
122
- expect { EvaluationReason::rule_match(true, "x") }.to raise_error(ArgumentError)
123
- expect { EvaluationReason::rule_match(1, nil) }.not_to raise_error # we allow nil rule_id for backward compatibility
124
- expect { EvaluationReason::rule_match(1, 9) }.to raise_error(ArgumentError)
125
- expect { EvaluationReason::prerequisite_failed(nil) }.to raise_error(ArgumentError)
126
- expect { EvaluationReason::prerequisite_failed(9) }.to raise_error(ArgumentError)
127
- expect { EvaluationReason::error(nil) }.to raise_error(ArgumentError)
128
- expect { EvaluationReason::error(9) }.to raise_error(ArgumentError)
129
- end
130
-
131
- it "does not allow direct access to constructor" do
132
- expect { EvaluationReason.new(:off, nil, nil, nil, nil) }.to raise_error(NoMethodError)
133
- end
134
- end
135
- end
@@ -1,197 +0,0 @@
1
- require "ldclient-rb/impl/event_sender"
2
-
3
- require "http_util"
4
- require "spec_helper"
5
-
6
- require "time"
7
-
8
- module LaunchDarkly
9
- module Impl
10
- describe EventSender do
11
- subject { EventSender }
12
-
13
- let(:sdk_key) { "sdk_key" }
14
- let(:fake_data) { '{"things":[]}' }
15
-
16
- def make_sender(server)
17
- subject.new(sdk_key, Config.new(events_uri: server.base_uri.to_s, logger: $null_log), nil, 0.1)
18
- end
19
-
20
- def with_sender_and_server
21
- with_server do |server|
22
- yield make_sender(server), server
23
- end
24
- end
25
-
26
- it "sends analytics event data" do
27
- with_sender_and_server do |es, server|
28
- server.setup_ok_response("/bulk", "")
29
-
30
- result = es.send_event_data(fake_data, "", false)
31
-
32
- expect(result.success).to be true
33
- expect(result.must_shutdown).to be false
34
- expect(result.time_from_server).not_to be_nil
35
-
36
- req = server.await_request
37
- expect(req.body).to eq fake_data
38
- expect(req.header).to include({
39
- "authorization" => [ sdk_key ],
40
- "content-type" => [ "application/json" ],
41
- "user-agent" => [ "RubyClient/" + LaunchDarkly::VERSION ],
42
- "x-launchdarkly-event-schema" => [ "3" ],
43
- "connection" => [ "Keep-Alive" ]
44
- })
45
- expect(req.header['x-launchdarkly-payload-id']).not_to eq []
46
- end
47
- end
48
-
49
- it "can use a socket factory" do
50
- with_server do |server|
51
- server.setup_ok_response("/bulk", "")
52
-
53
- config = Config.new(events_uri: "http://events.com/bulk", socket_factory: SocketFactoryFromHash.new({"events.com" => server.port}), logger: $null_log)
54
- es = subject.new(sdk_key, config, nil, 0.1)
55
-
56
- result = es.send_event_data(fake_data, "", false)
57
-
58
- expect(result.success).to be true
59
- req = server.await_request
60
- expect(req.body).to eq fake_data
61
- expect(req.host).to eq "events.com"
62
- end
63
- end
64
-
65
- it "generates a new payload ID for each payload" do
66
- with_sender_and_server do |es, server|
67
- server.setup_ok_response("/bulk", "")
68
-
69
- result1 = es.send_event_data(fake_data, "", false)
70
- result2 = es.send_event_data(fake_data, "", false)
71
- expect(result1.success).to be true
72
- expect(result2.success).to be true
73
-
74
- req1, body1 = server.await_request_with_body
75
- req2, body2 = server.await_request_with_body
76
- expect(body1).to eq fake_data
77
- expect(body2).to eq fake_data
78
- expect(req1.header['x-launchdarkly-payload-id']).not_to eq req2.header['x-launchdarkly-payload-id']
79
- end
80
- end
81
-
82
- it "sends diagnostic event data" do
83
- with_sender_and_server do |es, server|
84
- server.setup_ok_response("/diagnostic", "")
85
-
86
- result = es.send_event_data(fake_data, "", true)
87
-
88
- expect(result.success).to be true
89
- expect(result.must_shutdown).to be false
90
- expect(result.time_from_server).not_to be_nil
91
-
92
- req, body = server.await_request_with_body
93
- expect(body).to eq fake_data
94
- expect(req.header).to include({
95
- "authorization" => [ sdk_key ],
96
- "content-type" => [ "application/json" ],
97
- "user-agent" => [ "RubyClient/" + LaunchDarkly::VERSION ],
98
- "connection" => [ "Keep-Alive" ]
99
- })
100
- expect(req.header['x-launchdarkly-event-schema']).to eq []
101
- expect(req.header['x-launchdarkly-payload-id']).to eq []
102
- end
103
- end
104
-
105
- it "can use a proxy server" do
106
- with_server do |server|
107
- server.setup_ok_response("/bulk", "")
108
-
109
- with_server(StubProxyServer.new) do |proxy|
110
- begin
111
- ENV["http_proxy"] = proxy.base_uri.to_s
112
-
113
- es = make_sender(server)
114
-
115
- result = es.send_event_data(fake_data, "", false)
116
-
117
- expect(result.success).to be true
118
-
119
- req, body = server.await_request_with_body
120
- expect(body).to eq fake_data
121
- ensure
122
- ENV["http_proxy"] = nil
123
- end
124
- end
125
- end
126
- end
127
-
128
- [400, 408, 429, 500].each do |status|
129
- it "handles recoverable error #{status}" do
130
- with_sender_and_server do |es, server|
131
- req_count = 0
132
- server.setup_response("/bulk") do |req, res|
133
- req_count = req_count + 1
134
- res.status = req_count == 2 ? 200 : status
135
- end
136
-
137
- result = es.send_event_data(fake_data, "", false)
138
-
139
- expect(result.success).to be true
140
- expect(result.must_shutdown).to be false
141
- expect(result.time_from_server).not_to be_nil
142
-
143
- expect(server.requests.count).to eq 2
144
- req1, body1 = server.await_request_with_body
145
- req2, body2 = server.await_request_with_body
146
- expect(body1).to eq fake_data
147
- expect(body2).to eq fake_data
148
- expect(req1.header['x-launchdarkly-payload-id']).to eq req2.header['x-launchdarkly-payload-id']
149
- end
150
- end
151
- end
152
-
153
- [400, 408, 429, 500].each do |status|
154
- it "only retries error #{status} once" do
155
- with_sender_and_server do |es, server|
156
- req_count = 0
157
- server.setup_response("/bulk") do |req, res|
158
- req_count = req_count + 1
159
- res.status = req_count == 3 ? 200 : status
160
- end
161
-
162
- result = es.send_event_data(fake_data, "", false)
163
-
164
- expect(result.success).to be false
165
- expect(result.must_shutdown).to be false
166
- expect(result.time_from_server).to be_nil
167
-
168
- expect(server.requests.count).to eq 2
169
- req1, body1 = server.await_request_with_body
170
- req2, body2 = server.await_request_with_body
171
- expect(body1).to eq fake_data
172
- expect(body2).to eq fake_data
173
- expect(req1.header['x-launchdarkly-payload-id']).to eq req2.header['x-launchdarkly-payload-id']
174
- end
175
- end
176
- end
177
-
178
- [401, 403].each do |status|
179
- it "gives up after unrecoverable error #{status}" do
180
- with_sender_and_server do |es, server|
181
- server.setup_response("/bulk") do |req, res|
182
- res.status = status
183
- end
184
-
185
- result = es.send_event_data(fake_data, "", false)
186
-
187
- expect(result.success).to be false
188
- expect(result.must_shutdown).to be true
189
- expect(result.time_from_server).to be_nil
190
-
191
- expect(server.requests.count).to eq 1
192
- end
193
- end
194
- end
195
- end
196
- end
197
- end
@@ -1,63 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe LaunchDarkly::EventSummarizer do
4
- subject { LaunchDarkly::EventSummarizer }
5
-
6
- let(:user) { { key: "key" } }
7
-
8
- it "does not add identify event to summary" do
9
- es = subject.new
10
- snapshot = es.snapshot
11
- es.summarize_event({ kind: "identify", user: user })
12
-
13
- expect(es.snapshot).to eq snapshot
14
- end
15
-
16
- it "does not add custom event to summary" do
17
- es = subject.new
18
- snapshot = es.snapshot
19
- es.summarize_event({ kind: "custom", key: "whatever", user: user })
20
-
21
- expect(es.snapshot).to eq snapshot
22
- end
23
-
24
- it "tracks start and end dates" do
25
- es = subject.new
26
- flag = { key: "key" }
27
- event1 = { kind: "feature", creationDate: 2000, user: user }
28
- event2 = { kind: "feature", creationDate: 1000, user: user }
29
- event3 = { kind: "feature", creationDate: 1500, user: user }
30
- es.summarize_event(event1)
31
- es.summarize_event(event2)
32
- es.summarize_event(event3)
33
- data = es.snapshot
34
-
35
- expect(data.start_date).to be 1000
36
- expect(data.end_date).to be 2000
37
- end
38
-
39
- it "counts events" do
40
- es = subject.new
41
- flag1 = { key: "key1", version: 11 }
42
- flag2 = { key: "key2", version: 22 }
43
- event1 = { kind: "feature", key: "key1", version: 11, user: user, variation: 1, value: "value1", default: "default1" }
44
- event2 = { kind: "feature", key: "key1", version: 11, user: user, variation: 2, value: "value2", default: "default1" }
45
- event3 = { kind: "feature", key: "key2", version: 22, user: user, variation: 1, value: "value99", default: "default2" }
46
- event4 = { kind: "feature", key: "key1", version: 11, user: user, variation: 1, value: "value1", default: "default1" }
47
- event5 = { kind: "feature", key: "badkey", user: user, variation: nil, value: "default3", default: "default3" }
48
- [event1, event2, event3, event4, event5].each { |e| es.summarize_event(e) }
49
- data = es.snapshot
50
-
51
- expectedCounters = {
52
- { key: "key1", version: 11, variation: 1 } =>
53
- { count: 2, value: "value1", default: "default1" },
54
- { key: "key1", version: 11, variation: 2 } =>
55
- { count: 1, value: "value2", default: "default1" },
56
- { key: "key2", version: 22, variation: 1 } =>
57
- { count: 1, value: "value99", default: "default2" },
58
- { key: "badkey", version: nil, variation: nil } =>
59
- { count: 1, value: "default3", default: "default3" }
60
- }
61
- expect(data.counters).to eq expectedCounters
62
- end
63
- end