splitclient-rb 4.5.1-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +45 -0
- data/CHANGES.txt +147 -0
- data/Detailed-README.md +571 -0
- data/Gemfile +4 -0
- data/LICENSE +13 -0
- data/NEWS +75 -0
- data/README.md +43 -0
- data/Rakefile +24 -0
- data/exe/splitio +96 -0
- data/ext/murmurhash/MurmurHash3.java +162 -0
- data/lib/murmurhash/base.rb +58 -0
- data/lib/murmurhash/murmurhash.jar +0 -0
- data/lib/murmurhash/murmurhash_mri.rb +3 -0
- data/lib/splitclient-rb.rb +90 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapter.rb +12 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapters/map_adapter.rb +133 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapters/queue_adapter.rb +44 -0
- data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +165 -0
- data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +30 -0
- data/lib/splitclient-rb/cache/repositories/events/redis_repository.rb +29 -0
- data/lib/splitclient-rb/cache/repositories/events_repository.rb +41 -0
- data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +49 -0
- data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +78 -0
- data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +21 -0
- data/lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb +129 -0
- data/lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb +98 -0
- data/lib/splitclient-rb/cache/repositories/metrics_repository.rb +22 -0
- data/lib/splitclient-rb/cache/repositories/repository.rb +23 -0
- data/lib/splitclient-rb/cache/repositories/segments_repository.rb +82 -0
- data/lib/splitclient-rb/cache/repositories/splits_repository.rb +106 -0
- data/lib/splitclient-rb/cache/routers/impression_router.rb +52 -0
- data/lib/splitclient-rb/cache/senders/events_sender.rb +47 -0
- data/lib/splitclient-rb/cache/senders/impressions_formatter.rb +73 -0
- data/lib/splitclient-rb/cache/senders/impressions_sender.rb +67 -0
- data/lib/splitclient-rb/cache/senders/metrics_sender.rb +49 -0
- data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +48 -0
- data/lib/splitclient-rb/cache/stores/segment_store.rb +82 -0
- data/lib/splitclient-rb/cache/stores/split_store.rb +97 -0
- data/lib/splitclient-rb/clients/localhost_split_client.rb +92 -0
- data/lib/splitclient-rb/clients/split_client.rb +214 -0
- data/lib/splitclient-rb/engine/api/client.rb +74 -0
- data/lib/splitclient-rb/engine/api/events.rb +48 -0
- data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +55 -0
- data/lib/splitclient-rb/engine/api/impressions.rb +42 -0
- data/lib/splitclient-rb/engine/api/metrics.rb +61 -0
- data/lib/splitclient-rb/engine/api/segments.rb +62 -0
- data/lib/splitclient-rb/engine/api/splits.rb +60 -0
- data/lib/splitclient-rb/engine/evaluator/splitter.rb +123 -0
- data/lib/splitclient-rb/engine/matchers/all_keys_matcher.rb +46 -0
- data/lib/splitclient-rb/engine/matchers/between_matcher.rb +56 -0
- data/lib/splitclient-rb/engine/matchers/combiners.rb +9 -0
- data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +86 -0
- data/lib/splitclient-rb/engine/matchers/contains_all_matcher.rb +21 -0
- data/lib/splitclient-rb/engine/matchers/contains_any_matcher.rb +19 -0
- data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +30 -0
- data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +20 -0
- data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +26 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +27 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +54 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb +19 -0
- data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +53 -0
- data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +53 -0
- data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +24 -0
- data/lib/splitclient-rb/engine/matchers/negation_matcher.rb +60 -0
- data/lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb +23 -0
- data/lib/splitclient-rb/engine/matchers/set_matcher.rb +20 -0
- data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +26 -0
- data/lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb +45 -0
- data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +66 -0
- data/lib/splitclient-rb/engine/metrics/binary_search_latency_tracker.rb +128 -0
- data/lib/splitclient-rb/engine/metrics/metrics.rb +83 -0
- data/lib/splitclient-rb/engine/models/label.rb +8 -0
- data/lib/splitclient-rb/engine/models/split.rb +17 -0
- data/lib/splitclient-rb/engine/models/treatment.rb +3 -0
- data/lib/splitclient-rb/engine/parser/condition.rb +210 -0
- data/lib/splitclient-rb/engine/parser/evaluator.rb +118 -0
- data/lib/splitclient-rb/engine/parser/partition.rb +35 -0
- data/lib/splitclient-rb/engine/parser/split_adapter.rb +88 -0
- data/lib/splitclient-rb/exceptions/impressions_shutdown_exception.rb +4 -0
- data/lib/splitclient-rb/exceptions/sdk_blocker_timeout_expired_exception.rb +4 -0
- data/lib/splitclient-rb/localhost_split_factory.rb +13 -0
- data/lib/splitclient-rb/localhost_utils.rb +36 -0
- data/lib/splitclient-rb/managers/localhost_split_manager.rb +45 -0
- data/lib/splitclient-rb/managers/split_manager.rb +77 -0
- data/lib/splitclient-rb/split_config.rb +391 -0
- data/lib/splitclient-rb/split_factory.rb +35 -0
- data/lib/splitclient-rb/split_factory_builder.rb +16 -0
- data/lib/splitclient-rb/utilitites.rb +41 -0
- data/lib/splitclient-rb/version.rb +3 -0
- data/splitclient-rb.gemspec +50 -0
- data/splitio.yml.example +7 -0
- data/tasks/benchmark_get_treatment.rake +43 -0
- data/tasks/irb.rake +4 -0
- data/tasks/rspec.rake +3 -0
- metadata +321 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
module Cache
|
3
|
+
module Repositories
|
4
|
+
# Repository which forwards impressions interface to the selected adapter
|
5
|
+
class MetricsRepository < Repository
|
6
|
+
extend Forwardable
|
7
|
+
def_delegators :@adapter, :add_count, :add_latency, :add_gauge, :counts, :latencies, :gauges,
|
8
|
+
:clear_counts, :clear_latencies, :clear_gauges, :clear
|
9
|
+
|
10
|
+
def initialize(adapter, config)
|
11
|
+
@config = config
|
12
|
+
@adapter = case adapter.class.to_s
|
13
|
+
when 'SplitIoClient::Cache::Adapters::MemoryAdapter'
|
14
|
+
Repositories::Metrics::MemoryRepository.new(adapter, config)
|
15
|
+
when 'SplitIoClient::Cache::Adapters::RedisAdapter'
|
16
|
+
Repositories::Metrics::RedisRepository.new(adapter, config)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
module Cache
|
3
|
+
class Repository
|
4
|
+
def set_string(key, str)
|
5
|
+
@adapter.set_string(namespace_key(key), str)
|
6
|
+
end
|
7
|
+
|
8
|
+
def string(key)
|
9
|
+
@adapter.string(namespace_key(key))
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def namespace_key(key = '')
|
15
|
+
"#{@config.redis_namespace}#{key}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def impressions_metrics_key(key)
|
19
|
+
namespace_key("/#{@config.language}-#{@config.version}/#{@config.machine_ip}/#{key}")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
module Cache
|
3
|
+
module Repositories
|
4
|
+
class SegmentsRepository < Repository
|
5
|
+
KEYS_SLICE = 3000
|
6
|
+
|
7
|
+
attr_reader :adapter
|
8
|
+
|
9
|
+
def initialize(adapter, config)
|
10
|
+
@adapter = adapter
|
11
|
+
@config = config
|
12
|
+
|
13
|
+
@adapter.set_bool(namespace_key('.ready'), false)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Receives segment data, adds and removes segements from the store
|
17
|
+
def add_to_segment(segment)
|
18
|
+
name = segment[:name]
|
19
|
+
|
20
|
+
@adapter.initialize_set(segment_data(name)) unless @adapter.exists?(segment_data(name))
|
21
|
+
|
22
|
+
add_keys(name, segment[:added])
|
23
|
+
remove_keys(name, segment[:removed])
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_segment_keys(name)
|
27
|
+
@adapter.get_set(segment_data(name))
|
28
|
+
end
|
29
|
+
|
30
|
+
def in_segment?(name, key)
|
31
|
+
@adapter.in_set?(segment_data(name), key)
|
32
|
+
end
|
33
|
+
|
34
|
+
def used_segment_names
|
35
|
+
@adapter.get_set(namespace_key('.segments.registered'))
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_change_number(name, last_change)
|
39
|
+
@adapter.set_string(namespace_key(".segment.#{name}.till"), last_change)
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_change_number(name)
|
43
|
+
@adapter.string(namespace_key(".segment.#{name}.till")) || -1
|
44
|
+
end
|
45
|
+
|
46
|
+
def ready?
|
47
|
+
@adapter.string(namespace_key('.segments.ready')).to_i != -1
|
48
|
+
end
|
49
|
+
|
50
|
+
def not_ready!
|
51
|
+
@adapter.set_string(namespace_key('.segments.ready'), -1)
|
52
|
+
end
|
53
|
+
|
54
|
+
def ready!
|
55
|
+
@adapter.set_string(namespace_key('.segments.ready'), Time.now.utc.to_i)
|
56
|
+
end
|
57
|
+
|
58
|
+
def clear
|
59
|
+
@adapter.clear(namespace_key)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def segment_data(name)
|
65
|
+
namespace_key(".segment.#{name}")
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_keys(name, keys)
|
69
|
+
keys.each_slice(KEYS_SLICE) do |keys_slice|
|
70
|
+
@adapter.add_to_set(segment_data(name), keys_slice)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def remove_keys(name, keys)
|
75
|
+
keys.each_slice(KEYS_SLICE) do |keys_slice|
|
76
|
+
@adapter.delete_from_set(segment_data(name), keys_slice)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
|
3
|
+
module SplitIoClient
|
4
|
+
module Cache
|
5
|
+
module Repositories
|
6
|
+
class SplitsRepository < Repository
|
7
|
+
SPLITS_SLICE = 10
|
8
|
+
|
9
|
+
attr_reader :adapter
|
10
|
+
|
11
|
+
def initialize(adapter, config)
|
12
|
+
@adapter = adapter
|
13
|
+
@config = config
|
14
|
+
|
15
|
+
@adapter.set_string(namespace_key('.splits.till'), '-1')
|
16
|
+
@adapter.initialize_map(namespace_key('.segments.registered'))
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_split(split)
|
20
|
+
return unless split[:name]
|
21
|
+
|
22
|
+
@adapter.set_string(namespace_key(".split.#{split[:name]}"), split.to_json)
|
23
|
+
end
|
24
|
+
|
25
|
+
def remove_split(name)
|
26
|
+
@adapter.delete(namespace_key(".split.#{name}"))
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_splits(names, slice = SPLITS_SLICE)
|
30
|
+
splits = {}
|
31
|
+
|
32
|
+
names.each_slice(slice) do |splits_slice|
|
33
|
+
splits.merge!(
|
34
|
+
@adapter
|
35
|
+
.multiple_strings(splits_slice.map { |name| namespace_key(".split.#{name}") })
|
36
|
+
.map { |name, data| [name.gsub(namespace_key('.split.'), ''), data] }.to_h
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
splits.map do |name, data|
|
41
|
+
parsed_data = data ? JSON.parse(data, symbolize_names: true) : nil
|
42
|
+
[name.to_sym, parsed_data]
|
43
|
+
end.to_h
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_split(name)
|
47
|
+
split = @adapter.string(namespace_key(".split.#{name}"))
|
48
|
+
|
49
|
+
JSON.parse(split, symbolize_names: true) if split
|
50
|
+
end
|
51
|
+
|
52
|
+
def splits
|
53
|
+
splits_hash = {}
|
54
|
+
|
55
|
+
split_names.each do |name|
|
56
|
+
splits_hash[name] = get_split(name)
|
57
|
+
end
|
58
|
+
|
59
|
+
splits_hash
|
60
|
+
end
|
61
|
+
|
62
|
+
# Return an array of Split Names excluding control keys like splits.till
|
63
|
+
def split_names
|
64
|
+
@adapter.find_strings_by_prefix(namespace_key('.split.'))
|
65
|
+
.map { |split| split.gsub(namespace_key('.split.'), '') }
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_change_number(since)
|
69
|
+
@adapter.set_string(namespace_key('.splits.till'), since)
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_change_number
|
73
|
+
@adapter.string(namespace_key('.splits.till'))
|
74
|
+
end
|
75
|
+
|
76
|
+
def set_segment_names(names)
|
77
|
+
return if names.nil? || names.empty?
|
78
|
+
|
79
|
+
names.each do |name|
|
80
|
+
@adapter.add_to_set(namespace_key('.segments.registered'), name)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def exists?(name)
|
85
|
+
@adapter.exists?(namespace_key(".split.#{name}"))
|
86
|
+
end
|
87
|
+
|
88
|
+
def ready?
|
89
|
+
@adapter.string(namespace_key('.splits.ready')).to_i != -1
|
90
|
+
end
|
91
|
+
|
92
|
+
def not_ready!
|
93
|
+
@adapter.set_string(namespace_key('.splits.ready'), -1)
|
94
|
+
end
|
95
|
+
|
96
|
+
def ready!
|
97
|
+
@adapter.set_string(namespace_key('.splits.ready'), Time.now.utc.to_i)
|
98
|
+
end
|
99
|
+
|
100
|
+
def clear
|
101
|
+
@adapter.clear(namespace_key)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
class ImpressionRouter
|
3
|
+
attr_reader :router_thread
|
4
|
+
|
5
|
+
def initialize(config)
|
6
|
+
@config = config
|
7
|
+
@listener = config.impression_listener
|
8
|
+
@queue = Queue.new
|
9
|
+
router_thread
|
10
|
+
|
11
|
+
if defined?(PhusionPassenger)
|
12
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
13
|
+
router_thread if forked
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def add(impression)
|
19
|
+
@queue.push(impression)
|
20
|
+
end
|
21
|
+
|
22
|
+
def add_bulk(impressions)
|
23
|
+
impressions[:split_names].each do |split_name|
|
24
|
+
@queue.push(
|
25
|
+
split_name: split_name.to_s,
|
26
|
+
matching_key: impressions[:matching_key],
|
27
|
+
bucketing_key: impressions[:bucketing_key],
|
28
|
+
treatment: {
|
29
|
+
label: impressions[:treatments_labels_change_numbers][split_name.to_sym][:label],
|
30
|
+
treatment: impressions[:treatments_labels_change_numbers][split_name.to_sym][:treatment],
|
31
|
+
change_number: impressions[:treatments_labels_change_numbers][split_name.to_sym][:change_number]
|
32
|
+
},
|
33
|
+
attributes: impressions[:attributes]
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def router_thread
|
41
|
+
@config.threads[:impression_router] = Thread.new do
|
42
|
+
loop do
|
43
|
+
begin
|
44
|
+
@listener.log(@queue.pop)
|
45
|
+
rescue StandardError => error
|
46
|
+
@config.log_found_exception(__method__.to_s, error)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
module Cache
|
3
|
+
module Senders
|
4
|
+
class EventsSender
|
5
|
+
def initialize(events_repository, config, api_key)
|
6
|
+
@events_repository = events_repository
|
7
|
+
@config = config
|
8
|
+
@api_key = api_key
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
if ENV['SPLITCLIENT_ENV'] == 'test'
|
13
|
+
post_events
|
14
|
+
else
|
15
|
+
events_thread
|
16
|
+
|
17
|
+
if defined?(PhusionPassenger)
|
18
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
19
|
+
events_thread if forked
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def events_thread
|
28
|
+
@config.threads[:events_sender] = Thread.new do
|
29
|
+
@config.logger.info('Starting events service')
|
30
|
+
|
31
|
+
loop do
|
32
|
+
post_events
|
33
|
+
|
34
|
+
sleep(SplitIoClient::Utilities.randomize_interval(@config.events_push_rate))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def post_events
|
40
|
+
SplitIoClient::Api::Events.new(@api_key, @config, @events_repository.clear).post
|
41
|
+
rescue StandardError => error
|
42
|
+
@config.log_found_exception(__method__.to_s, error)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
module Cache
|
3
|
+
module Senders
|
4
|
+
class ImpressionsFormatter
|
5
|
+
def initialize(impressions_repository)
|
6
|
+
@impressions_repository = impressions_repository
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(raw_impressions)
|
10
|
+
impressions = raw_impressions ? raw_impressions : @impressions_repository.clear
|
11
|
+
formatted_impressions = []
|
12
|
+
filtered_impressions = filter_impressions(impressions)
|
13
|
+
|
14
|
+
return [] if impressions.empty? || filtered_impressions.empty?
|
15
|
+
|
16
|
+
formatted_impressions = unique_features(filtered_impressions).each_with_object([]) do |feature, memo|
|
17
|
+
ip = nil
|
18
|
+
current_impressions =
|
19
|
+
filtered_impressions
|
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
|
+
|
33
|
+
memo << {
|
34
|
+
testName: feature.to_sym,
|
35
|
+
keyImpressions: current_impressions,
|
36
|
+
ip: ip
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
formatted_impressions
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def unique_features(impressions)
|
46
|
+
impressions.map { |impression| impression[:feature] }.uniq
|
47
|
+
end
|
48
|
+
|
49
|
+
# Filter seen impressions by impression_hash
|
50
|
+
def filter_impressions(unfiltered_impressions)
|
51
|
+
impressions_seen = []
|
52
|
+
|
53
|
+
unfiltered_impressions.each_with_object([]) do |impression, impressions|
|
54
|
+
impression_hash = impression_hash(impression)
|
55
|
+
|
56
|
+
next if impressions_seen.include?(impression_hash)
|
57
|
+
|
58
|
+
impressions_seen << impression_hash
|
59
|
+
impressions << impression
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def impression_hash(impression)
|
64
|
+
"#{impression[:feature]}:" \
|
65
|
+
"#{impression[:impressions]['keyName']}:" \
|
66
|
+
"#{impression[:impressions]['bucketingKey']}:" \
|
67
|
+
"#{impression[:impressions]['changeNumber']}:" \
|
68
|
+
"#{impression[:impressions]['treatment']}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module SplitIoClient
|
2
|
+
module Cache
|
3
|
+
module Senders
|
4
|
+
class ImpressionsSender
|
5
|
+
def initialize(impressions_repository, config, api_key)
|
6
|
+
@impressions_repository = impressions_repository
|
7
|
+
@config = config
|
8
|
+
@api_key = api_key
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
# Disable impressions if @config.impressions_queue_size == -1
|
13
|
+
if @config.impressions_queue_size < 0
|
14
|
+
@config.logger.info('Disabling impressions service by config')
|
15
|
+
return
|
16
|
+
end
|
17
|
+
|
18
|
+
if ENV['SPLITCLIENT_ENV'] == 'test'
|
19
|
+
post_impressions
|
20
|
+
else
|
21
|
+
impressions_thread
|
22
|
+
|
23
|
+
if defined?(PhusionPassenger)
|
24
|
+
PhusionPassenger.on_event(:starting_worker_process) do |forked|
|
25
|
+
impressions_thread if forked
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def impressions_thread
|
34
|
+
@config.threads[:impressions_sender] = Thread.new do
|
35
|
+
begin
|
36
|
+
@config.logger.info('Starting impressions service')
|
37
|
+
|
38
|
+
loop do
|
39
|
+
post_impressions
|
40
|
+
|
41
|
+
sleep(SplitIoClient::Utilities.randomize_interval(@config.impressions_refresh_rate))
|
42
|
+
end
|
43
|
+
rescue SplitIoClient::ImpressionShutdownException
|
44
|
+
post_impressions
|
45
|
+
|
46
|
+
@impressions_repository.clear
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def post_impressions
|
52
|
+
impressions_client.post
|
53
|
+
rescue StandardError => error
|
54
|
+
@config.log_found_exception(__method__.to_s, error)
|
55
|
+
end
|
56
|
+
|
57
|
+
def formatted_impressions(raw_impressions = nil)
|
58
|
+
ImpressionsFormatter.new(@impressions_repository).call(raw_impressions)
|
59
|
+
end
|
60
|
+
|
61
|
+
def impressions_client
|
62
|
+
SplitIoClient::Api::Impressions.new(@api_key, @config, formatted_impressions)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|