ldclient-rb 3.0.3 → 4.0.0
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.
- 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
|