ldclient-rb 3.0.3 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +90 -0
- data/CHANGELOG.md +10 -0
- data/README.md +0 -1
- data/ldclient-rb.gemspec +8 -2
- data/lib/ldclient-rb.rb +5 -1
- data/lib/ldclient-rb/config.rb +41 -1
- data/lib/ldclient-rb/evaluation.rb +33 -17
- data/lib/ldclient-rb/event_summarizer.rb +52 -0
- data/lib/ldclient-rb/events.rb +383 -51
- data/lib/ldclient-rb/expiring_cache.rb +76 -0
- data/lib/ldclient-rb/ldclient.rb +44 -23
- data/lib/ldclient-rb/non_blocking_thread_pool.rb +46 -0
- data/lib/ldclient-rb/redis_store.rb +13 -17
- data/lib/ldclient-rb/simple_lru_cache.rb +24 -0
- data/lib/ldclient-rb/{event_serializer.rb → user_filter.rb} +17 -23
- data/lib/ldclient-rb/version.rb +1 -1
- data/spec/evaluation_spec.rb +44 -9
- data/spec/event_summarizer_spec.rb +63 -0
- data/spec/events_spec.rb +506 -0
- data/spec/expiring_cache_spec.rb +76 -0
- data/spec/fixtures/feature.json +1 -0
- data/spec/ldclient_spec.rb +94 -17
- data/spec/simple_lru_cache_spec.rb +24 -0
- data/spec/{event_serializer_spec.rb → user_filter_spec.rb} +23 -44
- metadata +49 -23
- data/circle.yml +0 -35
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'timecop'
|
2
|
+
|
3
|
+
describe LaunchDarkly::ExpiringCache do
|
4
|
+
subject { LaunchDarkly::ExpiringCache }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
Timecop.freeze(Time.now)
|
8
|
+
end
|
9
|
+
|
10
|
+
after(:each) do
|
11
|
+
Timecop.return
|
12
|
+
end
|
13
|
+
|
14
|
+
it "evicts entries based on TTL" do
|
15
|
+
c = subject.new(3, 300)
|
16
|
+
c[:a] = 1
|
17
|
+
c[:b] = 2
|
18
|
+
|
19
|
+
Timecop.freeze(Time.now + 330)
|
20
|
+
|
21
|
+
c[:c] = 3
|
22
|
+
|
23
|
+
expect(c[:a]).to be nil
|
24
|
+
expect(c[:b]).to be nil
|
25
|
+
expect(c[:c]).to eq 3
|
26
|
+
end
|
27
|
+
|
28
|
+
it "evicts entries based on max size" do
|
29
|
+
c = subject.new(2, 300)
|
30
|
+
c[:a] = 1
|
31
|
+
c[:b] = 2
|
32
|
+
c[:c] = 3
|
33
|
+
|
34
|
+
expect(c[:a]).to be nil
|
35
|
+
expect(c[:b]).to eq 2
|
36
|
+
expect(c[:c]).to eq 3
|
37
|
+
end
|
38
|
+
|
39
|
+
it "does not reset LRU on get" do
|
40
|
+
c = subject.new(2, 300)
|
41
|
+
c[:a] = 1
|
42
|
+
c[:b] = 2
|
43
|
+
c[:a]
|
44
|
+
c[:c] = 3
|
45
|
+
|
46
|
+
expect(c[:a]).to be nil
|
47
|
+
expect(c[:b]).to eq 2
|
48
|
+
expect(c[:c]).to eq 3
|
49
|
+
end
|
50
|
+
|
51
|
+
it "resets LRU on put" do
|
52
|
+
c = subject.new(2, 300)
|
53
|
+
c[:a] = 1
|
54
|
+
c[:b] = 2
|
55
|
+
c[:a] = 1
|
56
|
+
c[:c] = 3
|
57
|
+
|
58
|
+
expect(c[:a]).to eq 1
|
59
|
+
expect(c[:b]).to be nil
|
60
|
+
expect(c[:c]).to eq 3
|
61
|
+
end
|
62
|
+
|
63
|
+
it "resets TTL on put" do
|
64
|
+
c = subject.new(3, 300)
|
65
|
+
c[:a] = 1
|
66
|
+
c[:b] = 2
|
67
|
+
|
68
|
+
Timecop.freeze(Time.now + 330)
|
69
|
+
c[:a] = 1
|
70
|
+
c[:c] = 3
|
71
|
+
|
72
|
+
expect(c[:a]).to eq 1
|
73
|
+
expect(c[:b]).to be nil
|
74
|
+
expect(c[:c]).to eq 3
|
75
|
+
end
|
76
|
+
end
|
data/spec/fixtures/feature.json
CHANGED
data/spec/ldclient_spec.rb
CHANGED
@@ -3,7 +3,12 @@ require "spec_helper"
|
|
3
3
|
|
4
4
|
describe LaunchDarkly::LDClient do
|
5
5
|
subject { LaunchDarkly::LDClient }
|
6
|
-
let(:
|
6
|
+
let(:offline_config) { LaunchDarkly::Config.new({offline: true}) }
|
7
|
+
let(:offline_client) do
|
8
|
+
subject.new("secret", offline_config)
|
9
|
+
end
|
10
|
+
let(:update_processor) { NullUpdateProcessor.new }
|
11
|
+
let(:config) { LaunchDarkly::Config.new({send_events: false, update_processor: update_processor}) }
|
7
12
|
let(:client) do
|
8
13
|
subject.new("secret", config)
|
9
14
|
end
|
@@ -24,11 +29,74 @@ describe LaunchDarkly::LDClient do
|
|
24
29
|
JSON.parse(data, symbolize_names: true)
|
25
30
|
end
|
26
31
|
|
32
|
+
def event_processor
|
33
|
+
client.instance_variable_get(:@event_processor)
|
34
|
+
end
|
35
|
+
|
27
36
|
describe '#variation' do
|
28
37
|
it "will return the default value if the client is offline" do
|
29
|
-
result =
|
38
|
+
result = offline_client.variation("doesntmatter", user, "default")
|
30
39
|
expect(result).to eq "default"
|
31
40
|
end
|
41
|
+
|
42
|
+
it "queues a feature request event for an unknown feature" do
|
43
|
+
expect(event_processor).to receive(:add_event).with(hash_including(
|
44
|
+
kind: "feature", key: "badkey", user: user, value: "default", default: "default"
|
45
|
+
))
|
46
|
+
client.variation("badkey", user, "default")
|
47
|
+
end
|
48
|
+
|
49
|
+
it "queues a feature request event for an existing feature" do
|
50
|
+
config.feature_store.init({ LaunchDarkly::FEATURES => {} })
|
51
|
+
config.feature_store.upsert(LaunchDarkly::FEATURES, feature)
|
52
|
+
expect(event_processor).to receive(:add_event).with(hash_including(
|
53
|
+
kind: "feature",
|
54
|
+
key: feature[:key],
|
55
|
+
version: feature[:version],
|
56
|
+
user: user,
|
57
|
+
variation: 0,
|
58
|
+
value: true,
|
59
|
+
default: "default",
|
60
|
+
trackEvents: true,
|
61
|
+
debugEventsUntilDate: nil
|
62
|
+
))
|
63
|
+
client.variation(feature[:key], user, "default")
|
64
|
+
end
|
65
|
+
|
66
|
+
it "queues a feature event for an existing feature when user is nil" do
|
67
|
+
config.feature_store.init({ LaunchDarkly::FEATURES => {} })
|
68
|
+
config.feature_store.upsert(LaunchDarkly::FEATURES, feature)
|
69
|
+
expect(event_processor).to receive(:add_event).with(hash_including(
|
70
|
+
kind: "feature",
|
71
|
+
key: feature[:key],
|
72
|
+
version: feature[:version],
|
73
|
+
user: nil,
|
74
|
+
variation: nil,
|
75
|
+
value: "default",
|
76
|
+
default: "default",
|
77
|
+
trackEvents: true,
|
78
|
+
debugEventsUntilDate: nil
|
79
|
+
))
|
80
|
+
client.variation(feature[:key], nil, "default")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "queues a feature event for an existing feature when user key is nil" do
|
84
|
+
config.feature_store.init({ LaunchDarkly::FEATURES => {} })
|
85
|
+
config.feature_store.upsert(LaunchDarkly::FEATURES, feature)
|
86
|
+
bad_user = { name: "Bob" }
|
87
|
+
expect(event_processor).to receive(:add_event).with(hash_including(
|
88
|
+
kind: "feature",
|
89
|
+
key: feature[:key],
|
90
|
+
version: feature[:version],
|
91
|
+
user: bad_user,
|
92
|
+
variation: nil,
|
93
|
+
value: "default",
|
94
|
+
default: "default",
|
95
|
+
trackEvents: true,
|
96
|
+
debugEventsUntilDate: nil
|
97
|
+
))
|
98
|
+
client.variation(feature[:key], bad_user, "default")
|
99
|
+
end
|
32
100
|
end
|
33
101
|
|
34
102
|
describe '#secure_mode_hash' do
|
@@ -40,22 +108,24 @@ describe LaunchDarkly::LDClient do
|
|
40
108
|
|
41
109
|
describe '#track' do
|
42
110
|
it "queues up an custom event" do
|
43
|
-
expect(
|
111
|
+
expect(event_processor).to receive(:add_event).with(hash_including(kind: "custom", key: "custom_event_name", user: user, data: 42))
|
44
112
|
client.track("custom_event_name", user, 42)
|
45
113
|
end
|
114
|
+
|
46
115
|
it "sanitizes the user in the event" do
|
47
|
-
expect(
|
116
|
+
expect(event_processor).to receive(:add_event).with(hash_including(user: sanitized_numeric_key_user))
|
48
117
|
client.track("custom_event_name", numeric_key_user, nil)
|
49
118
|
end
|
50
119
|
end
|
51
120
|
|
52
121
|
describe '#identify' do
|
53
122
|
it "queues up an identify event" do
|
54
|
-
expect(
|
123
|
+
expect(event_processor).to receive(:add_event).with(hash_including(kind: "identify", key: user[:key], user: user))
|
55
124
|
client.identify(user)
|
56
125
|
end
|
126
|
+
|
57
127
|
it "sanitizes the user in the event" do
|
58
|
-
expect(
|
128
|
+
expect(event_processor).to receive(:add_event).with(hash_including(user: sanitized_numeric_key_user))
|
59
129
|
client.identify(numeric_key_user)
|
60
130
|
end
|
61
131
|
end
|
@@ -72,24 +142,31 @@ describe LaunchDarkly::LDClient do
|
|
72
142
|
end
|
73
143
|
|
74
144
|
describe 'with send_events: false' do
|
75
|
-
let(:config) { LaunchDarkly::Config.new({offline: true, send_events: false}) }
|
145
|
+
let(:config) { LaunchDarkly::Config.new({offline: true, send_events: false, update_processor: update_processor}) }
|
76
146
|
let(:client) { subject.new("secret", config) }
|
77
147
|
|
78
|
-
|
148
|
+
it "uses a NullEventProcessor" do
|
149
|
+
ep = client.instance_variable_get(:@event_processor)
|
150
|
+
expect(ep).to be_a(LaunchDarkly::NullEventProcessor)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe 'with send_events: true' do
|
155
|
+
let(:config_with_events) { LaunchDarkly::Config.new({offline: false, send_events: true, update_processor: update_processor}) }
|
156
|
+
let(:client_with_events) { subject.new("secret", config_with_events) }
|
79
157
|
|
80
|
-
it "does not
|
81
|
-
|
82
|
-
expect(
|
158
|
+
it "does not use a NullEventProcessor" do
|
159
|
+
ep = client_with_events.instance_variable_get(:@event_processor)
|
160
|
+
expect(ep).not_to be_a(LaunchDarkly::NullEventProcessor)
|
83
161
|
end
|
162
|
+
end
|
84
163
|
|
85
|
-
|
86
|
-
|
87
|
-
expect(queue.empty?).to be true
|
164
|
+
class NullUpdateProcessor
|
165
|
+
def start
|
88
166
|
end
|
89
167
|
|
90
|
-
|
91
|
-
|
92
|
-
expect(queue.empty?).to be true
|
168
|
+
def initialized?
|
169
|
+
true
|
93
170
|
end
|
94
171
|
end
|
95
172
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe LaunchDarkly::SimpleLRUCacheSet do
|
4
|
+
subject { LaunchDarkly::SimpleLRUCacheSet }
|
5
|
+
|
6
|
+
it "retains values up to capacity" do
|
7
|
+
lru = subject.new(3)
|
8
|
+
expect(lru.add("a")).to be false
|
9
|
+
expect(lru.add("b")).to be false
|
10
|
+
expect(lru.add("c")).to be false
|
11
|
+
expect(lru.add("a")).to be true
|
12
|
+
expect(lru.add("b")).to be true
|
13
|
+
expect(lru.add("c")).to be true
|
14
|
+
end
|
15
|
+
|
16
|
+
it "discards oldest value on overflow" do
|
17
|
+
lru = subject.new(2)
|
18
|
+
expect(lru.add("a")).to be false
|
19
|
+
expect(lru.add("b")).to be false
|
20
|
+
expect(lru.add("a")).to be true
|
21
|
+
expect(lru.add("c")).to be false # b is discarded as oldest
|
22
|
+
expect(lru.add("b")).to be false
|
23
|
+
end
|
24
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
|
-
describe LaunchDarkly::
|
4
|
-
subject { LaunchDarkly::
|
3
|
+
describe LaunchDarkly::UserFilter do
|
4
|
+
subject { LaunchDarkly::UserFilter }
|
5
5
|
|
6
6
|
let(:base_config) { LaunchDarkly::Config.new }
|
7
7
|
let(:config_with_all_attrs_private) { LaunchDarkly::Config.new({ all_attributes_private: true })}
|
@@ -45,68 +45,47 @@ describe LaunchDarkly::EventSerializer do
|
|
45
45
|
{ key: 'abc', anonymous: 'true', custom: { }, privateAttrs: [ 'bizzle', 'dizzle' ]}
|
46
46
|
}
|
47
47
|
|
48
|
-
|
49
|
-
def make_event(user)
|
50
|
-
{
|
51
|
-
creationDate: 1000000,
|
52
|
-
key: 'xyz',
|
53
|
-
kind: 'thing',
|
54
|
-
user: user
|
55
|
-
}
|
56
|
-
end
|
57
|
-
|
58
|
-
def parse_results(js)
|
59
|
-
JSON.parse(js, symbolize_names: true)
|
60
|
-
end
|
61
|
-
|
62
48
|
describe "serialize_events" do
|
63
49
|
it "includes all user attributes by default" do
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
expect(parse_results(j)).to eq [event]
|
50
|
+
uf = LaunchDarkly::UserFilter.new(base_config)
|
51
|
+
result = uf.transform_user_props(user)
|
52
|
+
expect(result).to eq user
|
68
53
|
end
|
69
54
|
|
70
55
|
it "hides all except key if all_attributes_private is true" do
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
expect(parse_results(j)).to eq [make_event(user_with_all_attrs_hidden)]
|
56
|
+
uf = LaunchDarkly::UserFilter.new(config_with_all_attrs_private)
|
57
|
+
result = uf.transform_user_props(user)
|
58
|
+
expect(result).to eq user_with_all_attrs_hidden
|
75
59
|
end
|
76
60
|
|
77
61
|
it "hides some attributes if private_attribute_names is set" do
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
expect(parse_results(j)).to eq [make_event(user_with_some_attrs_hidden)]
|
62
|
+
uf = LaunchDarkly::UserFilter.new(config_with_some_attrs_private)
|
63
|
+
result = uf.transform_user_props(user)
|
64
|
+
expect(result).to eq user_with_some_attrs_hidden
|
82
65
|
end
|
83
66
|
|
84
67
|
it "hides attributes specified in per-user privateAttrs" do
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
expect(parse_results(j)).to eq [make_event(user_with_own_specified_attr_hidden)]
|
68
|
+
uf = LaunchDarkly::UserFilter.new(base_config)
|
69
|
+
result = uf.transform_user_props(user_specifying_own_private_attr)
|
70
|
+
expect(result).to eq user_with_own_specified_attr_hidden
|
89
71
|
end
|
90
72
|
|
91
73
|
it "looks at both per-user privateAttrs and global config" do
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
expect(parse_results(j)).to eq [make_event(user_with_all_attrs_hidden)]
|
74
|
+
uf = LaunchDarkly::UserFilter.new(config_with_some_attrs_private)
|
75
|
+
result = uf.transform_user_props(user_specifying_own_private_attr)
|
76
|
+
expect(result).to eq user_with_all_attrs_hidden
|
96
77
|
end
|
97
78
|
|
98
79
|
it "strips out any unknown top-level attributes" do
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
expect(parse_results(j)).to eq [make_event(user)]
|
80
|
+
uf = LaunchDarkly::UserFilter.new(base_config)
|
81
|
+
result = uf.transform_user_props(user_with_unknown_top_level_attrs)
|
82
|
+
expect(result).to eq user
|
103
83
|
end
|
104
84
|
|
105
85
|
it "leaves the anonymous attribute as is" do
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
expect(parse_results(j)).to eq [make_event(anon_user_with_all_attrs_hidden)]
|
86
|
+
uf = LaunchDarkly::UserFilter.new(config_with_all_attrs_private)
|
87
|
+
result = uf.transform_user_props(anon_user)
|
88
|
+
expect(result).to eq anon_user_with_all_attrs_hidden
|
110
89
|
end
|
111
90
|
end
|
112
91
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ldclient-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 4.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- LaunchDarkly
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-05-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.7'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: rake
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '10.0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '10.0'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: rspec
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,19 +81,47 @@ dependencies:
|
|
95
81
|
- !ruby/object:Gem::Version
|
96
82
|
version: 2.1.2
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '10.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '10.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec_junit_formatter
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.3.0
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.3.0
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: timecop
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
115
|
- - "~>"
|
102
116
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
117
|
+
version: 0.9.1
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
122
|
- - "~>"
|
109
123
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
124
|
+
version: 0.9.1
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: json
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -302,6 +316,7 @@ extensions:
|
|
302
316
|
- ext/mkrf_conf.rb
|
303
317
|
extra_rdoc_files: []
|
304
318
|
files:
|
319
|
+
- ".circleci/config.yml"
|
305
320
|
- ".gitignore"
|
306
321
|
- ".hound.yml"
|
307
322
|
- ".rspec"
|
@@ -314,28 +329,33 @@ files:
|
|
314
329
|
- LICENSE.txt
|
315
330
|
- README.md
|
316
331
|
- Rakefile
|
317
|
-
- circle.yml
|
318
332
|
- ext/mkrf_conf.rb
|
319
333
|
- ldclient-rb.gemspec
|
320
334
|
- lib/ldclient-rb.rb
|
321
335
|
- lib/ldclient-rb/cache_store.rb
|
322
336
|
- lib/ldclient-rb/config.rb
|
323
337
|
- lib/ldclient-rb/evaluation.rb
|
324
|
-
- lib/ldclient-rb/
|
338
|
+
- lib/ldclient-rb/event_summarizer.rb
|
325
339
|
- lib/ldclient-rb/events.rb
|
340
|
+
- lib/ldclient-rb/expiring_cache.rb
|
326
341
|
- lib/ldclient-rb/in_memory_store.rb
|
327
342
|
- lib/ldclient-rb/ldclient.rb
|
328
343
|
- lib/ldclient-rb/memoized_value.rb
|
329
344
|
- lib/ldclient-rb/newrelic.rb
|
345
|
+
- lib/ldclient-rb/non_blocking_thread_pool.rb
|
330
346
|
- lib/ldclient-rb/polling.rb
|
331
347
|
- lib/ldclient-rb/redis_store.rb
|
332
348
|
- lib/ldclient-rb/requestor.rb
|
349
|
+
- lib/ldclient-rb/simple_lru_cache.rb
|
333
350
|
- lib/ldclient-rb/stream.rb
|
351
|
+
- lib/ldclient-rb/user_filter.rb
|
334
352
|
- lib/ldclient-rb/version.rb
|
335
353
|
- scripts/release.sh
|
336
354
|
- spec/config_spec.rb
|
337
355
|
- spec/evaluation_spec.rb
|
338
|
-
- spec/
|
356
|
+
- spec/event_summarizer_spec.rb
|
357
|
+
- spec/events_spec.rb
|
358
|
+
- spec/expiring_cache_spec.rb
|
339
359
|
- spec/feature_store_spec_base.rb
|
340
360
|
- spec/fixtures/feature.json
|
341
361
|
- spec/fixtures/feature1.json
|
@@ -348,9 +368,11 @@ files:
|
|
348
368
|
- spec/redis_feature_store_spec.rb
|
349
369
|
- spec/requestor_spec.rb
|
350
370
|
- spec/segment_store_spec_base.rb
|
371
|
+
- spec/simple_lru_cache_spec.rb
|
351
372
|
- spec/spec_helper.rb
|
352
373
|
- spec/store_spec.rb
|
353
374
|
- spec/stream_spec.rb
|
375
|
+
- spec/user_filter_spec.rb
|
354
376
|
- spec/version_spec.rb
|
355
377
|
homepage: https://github.com/launchdarkly/ruby-client
|
356
378
|
licenses:
|
@@ -379,7 +401,9 @@ summary: LaunchDarkly SDK for Ruby
|
|
379
401
|
test_files:
|
380
402
|
- spec/config_spec.rb
|
381
403
|
- spec/evaluation_spec.rb
|
382
|
-
- spec/
|
404
|
+
- spec/event_summarizer_spec.rb
|
405
|
+
- spec/events_spec.rb
|
406
|
+
- spec/expiring_cache_spec.rb
|
383
407
|
- spec/feature_store_spec_base.rb
|
384
408
|
- spec/fixtures/feature.json
|
385
409
|
- spec/fixtures/feature1.json
|
@@ -392,7 +416,9 @@ test_files:
|
|
392
416
|
- spec/redis_feature_store_spec.rb
|
393
417
|
- spec/requestor_spec.rb
|
394
418
|
- spec/segment_store_spec_base.rb
|
419
|
+
- spec/simple_lru_cache_spec.rb
|
395
420
|
- spec/spec_helper.rb
|
396
421
|
- spec/store_spec.rb
|
397
422
|
- spec/stream_spec.rb
|
423
|
+
- spec/user_filter_spec.rb
|
398
424
|
- spec/version_spec.rb
|