launchdarkly-server-sdk 6.2.3 → 6.3.1

Sign up to get free protection for your applications and to get access to all the features.
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