splitclient-rb 5.1.3.pre.rc1-java → 5.1.3.pre.rc2-java
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/.rubocop.yml +3 -0
- data/CHANGES.txt +1 -1
- data/NEWS +1 -1
- data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +11 -5
- data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +22 -20
- data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +29 -51
- data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +34 -6
- data/lib/splitclient-rb/cache/senders/events_sender.rb +2 -0
- data/lib/splitclient-rb/cache/senders/impressions_formatter.rb +31 -24
- data/lib/splitclient-rb/cache/senders/impressions_sender.rb +2 -0
- data/lib/splitclient-rb/cache/senders/metrics_sender.rb +2 -0
- data/lib/splitclient-rb/clients/split_client.rb +6 -7
- data/lib/splitclient-rb/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6cb0311b168fb12d22bf8b707f307095383b9017
|
4
|
+
data.tar.gz: 90da2fd289742ed147bc2f1ba4604f94bf7b877f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab58655555d5889e00b4eea5c1e7a851f412e3c6b23845eed34f2c44725762fbb518c3acbc9edf738ec37901049db3c23a61de28aaf132ab34bd6f39af83e5c8
|
7
|
+
data.tar.gz: 6067f1366ccbe092b5b4595d57b001c630c9f7d0e7101888f17bbc3670699bb002ba1a82ee479c03483aa35f5dc1caafe43e2ab6bc6447287aa92d6da91ea28a
|
data/.rubocop.yml
CHANGED
data/CHANGES.txt
CHANGED
data/NEWS
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'json'
|
2
4
|
|
3
5
|
module SplitIoClient
|
@@ -85,8 +87,8 @@ module SplitIoClient
|
|
85
87
|
end
|
86
88
|
|
87
89
|
# Set
|
88
|
-
|
89
|
-
|
90
|
+
alias initialize_set initialize_map
|
91
|
+
alias find_sets_by_prefix find_strings_by_prefix
|
90
92
|
|
91
93
|
def add_to_set(key, val)
|
92
94
|
@redis.sadd(key, val)
|
@@ -126,7 +128,7 @@ module SplitIoClient
|
|
126
128
|
def get_from_queue(key, count)
|
127
129
|
items = @redis.lrange(key, 0, count - 1)
|
128
130
|
fetched_count = items.size
|
129
|
-
items_to_remove =
|
131
|
+
items_to_remove = fetched_count == count ? count : fetched_count
|
130
132
|
|
131
133
|
@redis.ltrim(key, items_to_remove, -1)
|
132
134
|
|
@@ -148,9 +150,9 @@ module SplitIoClient
|
|
148
150
|
@redis.incrby(key, inc)
|
149
151
|
end
|
150
152
|
|
151
|
-
def pipelined
|
153
|
+
def pipelined
|
152
154
|
@redis.pipelined do
|
153
|
-
|
155
|
+
yield
|
154
156
|
end
|
155
157
|
end
|
156
158
|
|
@@ -159,6 +161,10 @@ module SplitIoClient
|
|
159
161
|
|
160
162
|
keys.map { |key| @redis.del(key) }
|
161
163
|
end
|
164
|
+
|
165
|
+
def expire(key, seconds)
|
166
|
+
@redis.expire(key, seconds)
|
167
|
+
end
|
162
168
|
end
|
163
169
|
end
|
164
170
|
end
|
@@ -1,42 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Cache
|
3
5
|
module Repositories
|
4
6
|
module Impressions
|
5
|
-
class MemoryRepository
|
6
|
-
|
7
|
+
class MemoryRepository < ImpressionsRepository
|
7
8
|
def initialize(adapter)
|
8
9
|
@adapter = adapter
|
9
10
|
end
|
10
11
|
|
11
12
|
# Store impression data in the selected adapter
|
12
|
-
def add(split_name,
|
13
|
-
@adapter.add_to_queue(
|
13
|
+
def add(matching_key, bucketing_key, split_name, treatment, time)
|
14
|
+
@adapter.add_to_queue(
|
15
|
+
m: metadata,
|
16
|
+
i: impression_data(
|
17
|
+
matching_key,
|
18
|
+
bucketing_key,
|
19
|
+
split_name,
|
20
|
+
treatment,
|
21
|
+
time
|
22
|
+
)
|
23
|
+
)
|
14
24
|
rescue ThreadError # queue is full
|
15
25
|
if random_sampler.rand(1..1000) <= 2 # log only 0.2 % of the time
|
16
|
-
SplitIoClient.configuration.logger.warn("Dropping impressions. Current size is
|
17
|
-
|
26
|
+
SplitIoClient.configuration.logger.warn("Dropping impressions. Current size is \
|
27
|
+
#{SplitIoClient.configuration.impressions_queue_size}. " \
|
28
|
+
'Consider increasing impressions_queue_size')
|
18
29
|
end
|
19
30
|
end
|
20
31
|
|
21
32
|
def add_bulk(key, bucketing_key, treatments, time)
|
22
33
|
treatments.each do |split_name, treatment|
|
23
|
-
add(
|
24
|
-
split_name,
|
25
|
-
'keyName' => key,
|
26
|
-
'bucketingKey' => bucketing_key,
|
27
|
-
'treatment' => treatment[:treatment],
|
28
|
-
'label' => SplitIoClient.configuration.labels_enabled ? treatment[:label] : nil,
|
29
|
-
'changeNumber' => treatment[:change_number],
|
30
|
-
'time' => time
|
31
|
-
)
|
34
|
+
add(key, bucketing_key, split_name, treatment, time)
|
32
35
|
end
|
33
36
|
end
|
34
37
|
|
35
|
-
def
|
36
|
-
return [] if SplitIoClient.configuration.impressions_bulk_size
|
37
|
-
|
38
|
-
|
39
|
-
end
|
38
|
+
def batch
|
39
|
+
return [] if SplitIoClient.configuration.impressions_bulk_size.zero?
|
40
|
+
|
41
|
+
@adapter.get_batch(SplitIoClient.configuration.impressions_bulk_size)
|
40
42
|
end
|
41
43
|
|
42
44
|
private
|
@@ -1,75 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Cache
|
3
5
|
module Repositories
|
4
6
|
module Impressions
|
5
|
-
class RedisRepository <
|
7
|
+
class RedisRepository < ImpressionsRepository
|
8
|
+
EXPIRE_SECONDS = 3600
|
6
9
|
|
7
10
|
def initialize(adapter)
|
8
11
|
@adapter = adapter
|
9
12
|
end
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
@adapter.add_to_set(
|
14
|
-
impressions_metrics_key("impressions.#{split_name}"),
|
15
|
-
data.to_json
|
16
|
-
)
|
14
|
+
def add(matching_key, bucketing_key, split_name, treatment, time)
|
15
|
+
add_bulk(matching_key, bucketing_key, { split_name => treatment }, time)
|
17
16
|
end
|
18
17
|
|
19
|
-
def add_bulk(
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
18
|
+
def add_bulk(matching_key, bucketing_key, treatments, time)
|
19
|
+
impressions = treatments.map do |split_name, treatment|
|
20
|
+
{
|
21
|
+
m: metadata,
|
22
|
+
i: impression_data(
|
23
|
+
matching_key,
|
24
|
+
bucketing_key,
|
25
|
+
split_name,
|
26
|
+
treatment,
|
27
|
+
time
|
28
|
+
)
|
29
|
+
}.to_json
|
30
30
|
end
|
31
|
-
end
|
32
|
-
|
33
|
-
# Get random impressions from redis in batches of size SplitIoClient.configuration.impressions_bulk_size,
|
34
|
-
# delete fetched impressions afterwards
|
35
|
-
def get_batch
|
36
|
-
impressions = impression_keys.each_with_object([]) do |key, memo|
|
37
|
-
ip = key.split('/')[-2] # 'prefix/sdk_lang/ip/impressions.name' -> ip
|
38
|
-
if ip.nil?
|
39
|
-
SplitIoClient.configuration.logger.warn("Impressions IP parse error for key: #{key}")
|
40
|
-
next
|
41
|
-
end
|
42
|
-
split_name = key.split('.').last
|
43
|
-
members = @adapter.random_set_elements(key, SplitIoClient.configuration.impressions_bulk_size)
|
44
|
-
members.each do |impression|
|
45
|
-
parsed_impression = JSON.parse(impression)
|
46
31
|
|
47
|
-
|
48
|
-
feature: split_name.to_sym,
|
49
|
-
impressions: parsed_impression,
|
50
|
-
ip: ip
|
51
|
-
}
|
52
|
-
end
|
32
|
+
impressions_list_size = @adapter.add_to_queue(key, impressions)
|
53
33
|
|
54
|
-
|
34
|
+
# Synchronizer might not be running
|
35
|
+
@adapter.expire(key, EXPIRE_SECONDS) if impressions.size == impressions_list_size
|
36
|
+
end
|
55
37
|
|
38
|
+
def batch
|
39
|
+
@adapter.get_from_queue(key, SplitIoClient.configuration.impressions_bulk_size).map do |e|
|
40
|
+
impression = JSON.parse(e, symbolize_names: true)
|
41
|
+
impression[:i][:f] = impression[:i][:f].to_sym
|
42
|
+
impression
|
56
43
|
end
|
57
|
-
impressions
|
58
44
|
rescue StandardError => e
|
59
45
|
SplitIoClient.configuration.logger.error("Exception while clearing impressions cache: #{e}")
|
60
|
-
|
61
46
|
[]
|
62
47
|
end
|
63
48
|
|
64
|
-
|
65
|
-
|
66
|
-
# Get all sets by prefix
|
67
|
-
def impression_keys
|
68
|
-
@adapter.find_sets_by_prefix("#{SplitIoClient.configuration.redis_namespace}/*/impressions.*")
|
69
|
-
rescue StandardError => e
|
70
|
-
SplitIoClient.configuration.logger.error("Exception while fetching impression_keys: #{e}")
|
71
|
-
|
72
|
-
[]
|
49
|
+
def key
|
50
|
+
@key ||= namespace_key('.impressions')
|
73
51
|
end
|
74
52
|
end
|
75
53
|
end
|
@@ -1,18 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Cache
|
3
5
|
module Repositories
|
4
6
|
# Repository which forwards impressions interface to the selected adapter
|
5
7
|
class ImpressionsRepository < Repository
|
6
8
|
extend Forwardable
|
7
|
-
def_delegators :@adapter, :add, :add_bulk, :
|
9
|
+
def_delegators :@adapter, :add, :add_bulk, :batch, :empty?
|
8
10
|
|
9
11
|
def initialize(adapter)
|
10
12
|
@adapter = case adapter.class.to_s
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
when 'SplitIoClient::Cache::Adapters::MemoryAdapter'
|
14
|
+
Repositories::Impressions::MemoryRepository.new(adapter)
|
15
|
+
when 'SplitIoClient::Cache::Adapters::RedisAdapter'
|
16
|
+
Repositories::Impressions::RedisRepository.new(adapter)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def impression_data(matching_key, bucketing_key, split_name, treatment, timestamp)
|
23
|
+
{
|
24
|
+
k: matching_key,
|
25
|
+
b: bucketing_key,
|
26
|
+
f: split_name,
|
27
|
+
t: treatment[:treatment],
|
28
|
+
r: applied_rule(treatment[:label]),
|
29
|
+
c: treatment[:change_number],
|
30
|
+
m: timestamp
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def metadata
|
35
|
+
{
|
36
|
+
s: "#{SplitIoClient.configuration.language}-#{SplitIoClient.configuration.version}",
|
37
|
+
i: SplitIoClient.configuration.machine_ip,
|
38
|
+
n: SplitIoClient.configuration.machine_name
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def applied_rule(label)
|
43
|
+
SplitIoClient.configuration.labels_enabled ? label : nil
|
16
44
|
end
|
17
45
|
end
|
18
46
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module SplitIoClient
|
2
4
|
module Cache
|
3
5
|
module Senders
|
@@ -7,29 +9,15 @@ module SplitIoClient
|
|
7
9
|
end
|
8
10
|
|
9
11
|
def call(raw_impressions)
|
10
|
-
impressions = raw_impressions
|
11
|
-
formatted_impressions = []
|
12
|
+
impressions = raw_impressions || @impressions_repository.batch
|
12
13
|
filtered_impressions = filter_impressions(impressions)
|
13
14
|
|
14
15
|
return [] if impressions.empty? || filtered_impressions.empty?
|
15
16
|
|
16
17
|
formatted_impressions = unique_features(filtered_impressions).each_with_object([]) do |feature, memo|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
.select { |impression| impression[:feature] == feature }
|
21
|
-
.map do |impression|
|
22
|
-
ip = impression[:ip]
|
23
|
-
{
|
24
|
-
keyName: impression[:impressions]['keyName'] || impression[:impressions]['key_name'],
|
25
|
-
treatment: impression[:impressions]['treatment'],
|
26
|
-
time: impression[:impressions]['time'],
|
27
|
-
bucketingKey: impression[:impressions]['bucketingKey'] || impression[:impressions]['bucketing_key'],
|
28
|
-
label: impression[:impressions]['label'],
|
29
|
-
changeNumber: impression[:impressions]['changeNumber'] || impression[:impressions]['change_number'],
|
30
|
-
}
|
31
|
-
end
|
32
|
-
|
18
|
+
feature_impressions = feature_impressions(filtered_impressions, feature)
|
19
|
+
ip = feature_impressions.first[:m][:i]
|
20
|
+
current_impressions = current_impressions(feature_impressions)
|
33
21
|
memo << {
|
34
22
|
testName: feature.to_sym,
|
35
23
|
keyImpressions: current_impressions,
|
@@ -42,8 +30,27 @@ module SplitIoClient
|
|
42
30
|
|
43
31
|
private
|
44
32
|
|
33
|
+
def feature_impressions(filtered_impressions, feature)
|
34
|
+
filtered_impressions.select do |impression|
|
35
|
+
impression[:i][:f] == feature
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def current_impressions(feature_impressions)
|
40
|
+
feature_impressions.map do |impression|
|
41
|
+
{
|
42
|
+
keyName: impression[:i][:k],
|
43
|
+
treatment: impression[:i][:t],
|
44
|
+
time: impression[:i][:m],
|
45
|
+
bucketingKey: impression[:i][:b],
|
46
|
+
label: impression[:i][:r],
|
47
|
+
changeNumber: impression[:i][:c]
|
48
|
+
}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
45
52
|
def unique_features(impressions)
|
46
|
-
impressions.map { |impression| impression[:
|
53
|
+
impressions.map { |impression| impression[:i][:f] }.uniq
|
47
54
|
end
|
48
55
|
|
49
56
|
# Filter seen impressions by impression_hash
|
@@ -61,11 +68,11 @@ module SplitIoClient
|
|
61
68
|
end
|
62
69
|
|
63
70
|
def impression_hash(impression)
|
64
|
-
"#{impression[:
|
65
|
-
"#{impression[:
|
66
|
-
"#{impression[:
|
67
|
-
"#{impression[:
|
68
|
-
"#{impression[:
|
71
|
+
"#{impression[:i][:f]}:" \
|
72
|
+
"#{impression[:i][:k]}:" \
|
73
|
+
"#{impression[:i][:b]}:" \
|
74
|
+
"#{impression[:i][:c]}:" \
|
75
|
+
"#{impression[:i][:t]}"
|
69
76
|
end
|
70
77
|
end
|
71
78
|
end
|
@@ -136,13 +136,12 @@ module SplitIoClient
|
|
136
136
|
|
137
137
|
return if SplitIoClient.configuration.disable_impressions || !store_impressions
|
138
138
|
|
139
|
-
@impressions_repository.add(
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
'changeNumber' => treatment[:change_number]
|
139
|
+
@impressions_repository.add(
|
140
|
+
matching_key,
|
141
|
+
bucketing_key,
|
142
|
+
split_name,
|
143
|
+
treatment,
|
144
|
+
time
|
146
145
|
)
|
147
146
|
|
148
147
|
route_impression(split_name, matching_key, bucketing_key, time, treatment, attributes)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: splitclient-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.1.3.pre.
|
4
|
+
version: 5.1.3.pre.rc2
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Split Software
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-12-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|