Skip to content

Commit 85e88c2

Browse files
committed
Updated post SS keys in chunks
1 parent 47c78b9 commit 85e88c2

File tree

4 files changed

+73
-22
lines changed

4 files changed

+73
-22
lines changed

lib/splitclient-rb/engine/impressions/unique_keys_tracker.rb

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ def initialize(config,
1414
@filter_adapter = filter_adapter
1515
@sender_adapter = sender_adapter
1616
@cache = cache
17-
@cache_max_size = config.unique_keys_cache_max_size
1817
@max_bulk_size = config.unique_keys_bulk_size
1918
@semaphore = Mutex.new
19+
@keys_size = 0
2020
end
2121

2222
def call
@@ -30,8 +30,9 @@ def track(feature_name, key)
3030
@filter_adapter.add(feature_name, key)
3131

3232
add_or_update(feature_name, key)
33+
@keys_size += 1
3334

34-
send_bulk_data if @cache.size >= @cache_max_size
35+
send_bulk_data if @keys_size >= @max_bulk_size
3536

3637
true
3738
rescue StandardError => e
@@ -75,14 +76,19 @@ def send_bulk_data
7576
return if @cache.empty?
7677

7778
uniques = @cache.clone
79+
keys_size = @keys_size
7880
@cache.clear
81+
@keys_size = 0
7982

80-
if uniques.size <= @max_bulk_size
83+
if keys_size <= @max_bulk_size
8184
@sender_adapter.record_uniques_key(uniques)
8285
return
8386
end
8487

85-
bulks = SplitIoClient::Utilities.split_bulk_to_send(uniques, uniques.size / @max_bulk_size)
88+
bulks = []
89+
uniques.each do |unique|
90+
bulks += check_keys_and_split_to_bulks(unique)
91+
end
8692

8793
bulks.each do |b|
8894
@sender_adapter.record_uniques_key(b)
@@ -91,6 +97,22 @@ def send_bulk_data
9197
rescue StandardError => e
9298
@config.log_found_exception(__method__.to_s, e)
9399
end
100+
101+
def check_keys_and_split_to_bulks(unique)
102+
unique_updated = []
103+
unique.each do |_, value|
104+
if value.size > @max_bulk_size
105+
sub_bulks = SplitIoClient::Utilities.split_bulk_to_send(value, value.size / @max_bulk_size)
106+
sub_bulks.each do |sub_bulk|
107+
unique_updated.add({ key: sub_bulk })
108+
end
109+
end
110+
unique_updated.add({ key: value })
111+
end
112+
return [unique] if unique_updated == {}
113+
114+
unique_updated
115+
end
94116
end
95117
end
96118
end

lib/splitclient-rb/split_config.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ def initialize(opts = {})
112112
@telemetry_service_url = opts[:telemetry_service_url] || SplitConfig.default_telemetry_service_url
113113

114114
@unique_keys_refresh_rate = SplitConfig.default_unique_keys_refresh_rate(@cache_adapter)
115-
@unique_keys_cache_max_size = SplitConfig.default_unique_keys_cache_max_size
115+
# @unique_keys_cache_max_size = SplitConfig.default_unique_keys_cache_max_size
116116
@unique_keys_bulk_size = SplitConfig.default_unique_keys_bulk_size(@cache_adapter)
117117

118118
@counter_refresh_rate = SplitConfig.default_counter_refresh_rate(@cache_adapter)
@@ -292,7 +292,7 @@ def initialize(opts = {})
292292
attr_accessor :on_demand_fetch_max_retries
293293

294294
attr_accessor :unique_keys_refresh_rate
295-
attr_accessor :unique_keys_cache_max_size
295+
#attr_accessor :unique_keys_cache_max_size
296296
attr_accessor :unique_keys_bulk_size
297297

298298
attr_accessor :counter_refresh_rate
@@ -498,9 +498,9 @@ def self.default_unique_keys_refresh_rate(adapter)
498498
900
499499
end
500500

501-
def self.default_unique_keys_cache_max_size
502-
30000
503-
end
501+
# def self.default_unique_keys_cache_max_size
502+
# 30000
503+
# end
504504

505505
def self.default_unique_keys_bulk_size(adapter)
506506
return 2000 if adapter == :redis

spec/engine/impressions/memory_unique_keys_tracker_spec.rb

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,17 @@
2121
it 'track - full cache and send bulk' do
2222
post_url = 'https://telemetry.split.io/api/v1/keys/ss'
2323
body_expect = {
24-
keys: [{ f: 'feature-test-0', ks: ['key_test-1', 'key_test-2'] }, { f: 'feature-test-1', ks: ['key_test-1'] }]
24+
keys: [{ f: 'feature-test-0', ks: ['key_test-1', 'key_test-2'] }]
25+
}.to_json
26+
27+
body_expect2 = {
28+
keys: [{ f: 'feature-test-1', ks: ['key_test-1', 'key_test-2'] }]
2529
}.to_json
2630

2731
stub_request(:post, post_url).with(body: body_expect).to_return(status: 200, body: '')
32+
stub_request(:post, post_url).with(body: body_expect2).to_return(status: 200, body: '')
2833

2934
cache = Concurrent::Hash.new
30-
config.unique_keys_cache_max_size = 2
3135
config.unique_keys_bulk_size = 2
3236
tracker = subject.new(config, filter_adapter, sender_adapter, cache)
3337

@@ -36,36 +40,61 @@
3640
expect(tracker.track("feature-test-#{i}", 'key_test-2')).to eq(true)
3741
end
3842

43+
expect(a_request(:post, post_url).with(body: body_expect2)).to have_been_made
3944
expect(a_request(:post, post_url).with(body: body_expect)).to have_been_made
4045

4146
cache.clear
4247
end
4348

44-
it 'track - full cache and send 2 bulks' do
49+
it 'track - full cache and send 4 bulks' do
4550
post_url = 'https://telemetry.split.io/api/v1/keys/ss'
4651
body_expect1 = {
47-
keys: [{ f: 'feature-test-0', ks: ['key-1', 'key-2'] }, { f: 'feature-test-2', ks: ['key-1', 'key-2'] }]
52+
keys: [{ f: 'feature-test-0', ks: ['key-1', 'key-2'] }]
4853
}.to_json
4954

5055
body_expect2 = {
51-
keys: [{ f: 'feature-test-1', ks: ['key-1', 'key-2'] }, { f: 'feature-test-3', ks: ['key-1'] }]
56+
keys: [{ f: 'feature-test-0', ks: ['key-3'] }, { f: 'feature-test-1', ks: ['key-1'] }]
57+
}.to_json
58+
59+
body_expect3 = {
60+
keys: [{ f: 'feature-test-1', ks: ['key-2', 'key-3'] }]
61+
}.to_json
62+
63+
body_expect4 = {
64+
keys: [{ f: 'feature-test-2', ks: ['key-1', 'key-2'] }]
65+
}.to_json
66+
67+
body_expect5 = {
68+
keys: [{ f: 'feature-test-2', ks: ['key-3'] }, { f: 'feature-test-3', ks: ['key-1'] }]
69+
}.to_json
70+
71+
body_expect6 = {
72+
keys: [{ f: 'feature-test-3', ks: ['key-2', 'key-3'] }]
5273
}.to_json
5374

5475
stub_request(:post, post_url).with(body: body_expect1).to_return(status: 200, body: '')
5576
stub_request(:post, post_url).with(body: body_expect2).to_return(status: 200, body: '')
77+
stub_request(:post, post_url).with(body: body_expect3).to_return(status: 200, body: '')
78+
stub_request(:post, post_url).with(body: body_expect4).to_return(status: 200, body: '')
79+
stub_request(:post, post_url).with(body: body_expect5).to_return(status: 200, body: '')
80+
stub_request(:post, post_url).with(body: body_expect6).to_return(status: 200, body: '')
5681

5782
cache = Concurrent::Hash.new
58-
config.unique_keys_cache_max_size = 4
5983
config.unique_keys_bulk_size = 2
6084
tracker = subject.new(config, filter_adapter, sender_adapter, cache)
6185

6286
4.times do |i|
6387
expect(tracker.track("feature-test-#{i}", 'key-1')).to eq(true)
6488
expect(tracker.track("feature-test-#{i}", 'key-2')).to eq(true)
89+
expect(tracker.track("feature-test-#{i}", 'key-3')).to eq(true)
6590
end
6691

6792
expect(a_request(:post, post_url).with(body: body_expect1)).to have_been_made
6893
expect(a_request(:post, post_url).with(body: body_expect2)).to have_been_made
94+
expect(a_request(:post, post_url).with(body: body_expect3)).to have_been_made
95+
expect(a_request(:post, post_url).with(body: body_expect4)).to have_been_made
96+
expect(a_request(:post, post_url).with(body: body_expect5)).to have_been_made
97+
expect(a_request(:post, post_url).with(body: body_expect6)).to have_been_made
6998

7099
cache.clear
71100
end
@@ -74,9 +103,8 @@
74103
context 'with sender_adapter_test' do
75104
let(:sender_adapter_test) { MemoryUniqueKeysSenderTest.new }
76105

77-
it 'track - should add elemets to cache' do
106+
it 'track - should trigger send when bulk size reached and add elemets to cache' do
78107
cache = Concurrent::Hash.new
79-
config.unique_keys_cache_max_size = 5
80108
config.unique_keys_bulk_size = 5
81109
tracker = subject.new(config, filter_adapter, sender_adapter_test, cache)
82110

@@ -85,24 +113,26 @@
85113
expect(tracker.track('feature_name_test', 'key_test-1')).to eq(true)
86114
expect(tracker.track('feature_name_test', 'key_test-2')).to eq(true)
87115
expect(tracker.track('other_test', 'key_test-2')).to eq(true)
88-
expect(tracker.track('other_test', 'key_test-35')).to eq(true)
89-
90116
expect(cache.size).to eq(2)
117+
expect(tracker.instance_variable_get(:@keys_size)).to eq(4)
118+
91119
expect(cache['feature_name_test'].include?('key_test')).to eq(true)
92120
expect(cache['feature_name_test'].include?('key_test-1')).to eq(true)
93121
expect(cache['feature_name_test'].include?('key_test-2')).to eq(true)
94122
expect(cache['feature_name_test'].include?('key_test-35')).to eq(false)
95123

96124
expect(cache['other_test'].include?('key_test-2')).to eq(true)
97-
expect(cache['other_test'].include?('key_test-35')).to eq(true)
98125
expect(cache['other_test'].include?('key_test-1')).to eq(false)
99126

127+
expect(tracker.track('other_test', 'key_test-35')).to eq(true)
128+
expect(cache.size).to eq(0)
129+
expect(tracker.instance_variable_get(:@keys_size)).to eq(0)
130+
100131
cache.clear
101132
end
102133

103134
it 'track - full cache and send bulk' do
104135
cache = Concurrent::Hash.new
105-
config.unique_keys_cache_max_size = 10
106136
config.unique_keys_bulk_size = 5
107137
tracker = subject.new(config, filter_adapter, sender_adapter_test, cache)
108138

spec/engine/impressions/redis_unique_keys_tracker_spec.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
key = "#{config.redis_namespace}.uniquekeys"
2727

2828
cache = Concurrent::Hash.new
29-
config.unique_keys_cache_max_size = 20
3029
config.unique_keys_bulk_size = 2
3130
tracker = subject.new(config, filter_adapter, sender_adapter, cache)
3231

0 commit comments

Comments
 (0)