splitclient-rb 1.0.2.wip → 8.11.1.pre.rc1-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 +5 -5
- data/.github/CODEOWNERS +1 -0
- data/.github/pull_request_template.md +9 -0
- data/.github/workflows/ci.yml +90 -0
- data/.github/workflows/update-license-year.yml +45 -0
- data/.gitignore +20 -0
- data/.rubocop.yml +76 -0
- data/.simplecov +1 -0
- data/CHANGES.txt +361 -2
- data/CONTRIBUTORS-GUIDE.md +49 -0
- data/Gemfile +2 -0
- data/LICENSE +3 -36
- data/NOTICE.txt +5 -0
- data/README.md +59 -127
- data/Rakefile +27 -3
- data/ext/murmurhash/MurmurHash3.java +302 -0
- data/gemfiles/faraday_after_0.13.gemfile +7 -0
- data/gemfiles/faraday_before_0.13.gemfile +8 -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/cache/adapters/cache_adapter.rb +130 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapter.rb +12 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapters/map_adapter.rb +137 -0
- data/lib/splitclient-rb/cache/adapters/memory_adapters/queue_adapter.rb +53 -0
- data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +178 -0
- data/lib/splitclient-rb/cache/fetchers/segment_fetcher.rb +83 -0
- data/lib/splitclient-rb/cache/fetchers/split_fetcher.rb +70 -0
- data/lib/splitclient-rb/cache/filter/bloom_filter.rb +67 -0
- data/lib/splitclient-rb/cache/filter/filter_adapter.rb +32 -0
- data/lib/splitclient-rb/cache/filter/flag_set_filter.rb +40 -0
- data/lib/splitclient-rb/cache/hashers/impression_hasher.rb +34 -0
- data/lib/splitclient-rb/cache/observers/impression_observer.rb +22 -0
- data/lib/splitclient-rb/cache/observers/noop_impression_observer.rb +10 -0
- data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +45 -0
- data/lib/splitclient-rb/cache/repositories/events/redis_repository.rb +35 -0
- data/lib/splitclient-rb/cache/repositories/events_repository.rb +61 -0
- data/lib/splitclient-rb/cache/repositories/flag_sets/memory_repository.rb +40 -0
- data/lib/splitclient-rb/cache/repositories/flag_sets/redis_repository.rb +49 -0
- data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +56 -0
- data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +57 -0
- data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +23 -0
- data/lib/splitclient-rb/cache/repositories/repository.rb +24 -0
- data/lib/splitclient-rb/cache/repositories/rule_based_segments_repository.rb +136 -0
- data/lib/splitclient-rb/cache/repositories/segments_repository.rb +124 -0
- data/lib/splitclient-rb/cache/repositories/splits_repository.rb +296 -0
- data/lib/splitclient-rb/cache/routers/impression_router.rb +60 -0
- data/lib/splitclient-rb/cache/senders/events_sender.rb +42 -0
- data/lib/splitclient-rb/cache/senders/impressions_adapter/memory_sender.rb +71 -0
- data/lib/splitclient-rb/cache/senders/impressions_adapter/redis_sender.rb +69 -0
- data/lib/splitclient-rb/cache/senders/impressions_count_sender.rb +43 -0
- data/lib/splitclient-rb/cache/senders/impressions_formatter.rb +95 -0
- data/lib/splitclient-rb/cache/senders/impressions_sender.rb +52 -0
- data/lib/splitclient-rb/cache/senders/impressions_sender_adapter.rb +21 -0
- data/lib/splitclient-rb/cache/senders/localhost_repo_cleaner.rb +47 -0
- data/lib/splitclient-rb/cache/stores/localhost_split_builder.rb +95 -0
- data/lib/splitclient-rb/cache/stores/localhost_split_store.rb +110 -0
- data/lib/splitclient-rb/cache/stores/store_utils.rb +13 -0
- data/lib/splitclient-rb/clients/split_client.rb +530 -0
- data/lib/splitclient-rb/constants.rb +16 -0
- data/lib/splitclient-rb/engine/api/client.rb +87 -0
- data/lib/splitclient-rb/engine/api/events.rb +57 -0
- data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +58 -0
- data/lib/splitclient-rb/engine/api/impressions.rb +79 -0
- data/lib/splitclient-rb/engine/api/segments.rb +78 -0
- data/lib/splitclient-rb/engine/api/splits.rb +139 -0
- data/lib/splitclient-rb/engine/api/telemetry_api.rb +47 -0
- data/lib/splitclient-rb/engine/auth_api_client.rb +100 -0
- data/lib/splitclient-rb/engine/back_off.rb +26 -0
- data/lib/splitclient-rb/engine/common/impressions_counter.rb +45 -0
- data/lib/splitclient-rb/engine/common/impressions_manager.rb +165 -0
- data/lib/splitclient-rb/engine/common/noop_impressions_counter.rb +27 -0
- data/lib/{splitclient-engine → splitclient-rb/engine}/evaluator/splitter.rb +35 -22
- data/lib/splitclient-rb/engine/events/events_delivery.rb +20 -0
- data/lib/splitclient-rb/engine/events/events_manager.rb +194 -0
- data/lib/splitclient-rb/engine/events/events_manager_config.rb +96 -0
- data/lib/splitclient-rb/engine/events/events_task.rb +50 -0
- data/lib/splitclient-rb/engine/events/noop_events_queue.rb +13 -0
- data/lib/splitclient-rb/engine/fallback_treatment_calculator.rb +48 -0
- data/lib/splitclient-rb/engine/impressions/noop_unique_keys_tracker.rb +17 -0
- data/lib/splitclient-rb/engine/impressions/unique_keys_tracker.rb +144 -0
- data/lib/{splitclient-engine → splitclient-rb/engine}/matchers/all_keys_matcher.rb +10 -21
- data/lib/splitclient-rb/engine/matchers/between_matcher.rb +47 -0
- data/lib/splitclient-rb/engine/matchers/between_semver_matcher.rb +33 -0
- data/lib/{splitclient-engine → splitclient-rb/engine}/matchers/combiners.rb +4 -6
- data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +80 -0
- data/lib/splitclient-rb/engine/matchers/contains_all_matcher.rb +20 -0
- data/lib/splitclient-rb/engine/matchers/contains_any_matcher.rb +16 -0
- data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +43 -0
- data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +26 -0
- data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +42 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +37 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +44 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_semver_matcher.rb +28 -0
- data/lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb +16 -0
- data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +43 -0
- data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_semver_matcher.rb +28 -0
- data/lib/splitclient-rb/engine/matchers/in_list_semver_matcher.rb +36 -0
- data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +43 -0
- data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb +28 -0
- data/lib/splitclient-rb/engine/matchers/matcher.rb +52 -0
- data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +29 -0
- data/lib/splitclient-rb/engine/matchers/negation_matcher.rb +47 -0
- data/lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb +22 -0
- data/lib/splitclient-rb/engine/matchers/prerequisites_matcher.rb +31 -0
- data/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb +78 -0
- data/lib/splitclient-rb/engine/matchers/semver.rb +201 -0
- data/lib/splitclient-rb/engine/matchers/set_matcher.rb +27 -0
- data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +40 -0
- data/lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb +28 -0
- data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +66 -0
- data/lib/splitclient-rb/engine/metrics/binary_search_latency_tracker.rb +66 -0
- data/lib/splitclient-rb/engine/models/evaluation_options.rb +9 -0
- data/lib/splitclient-rb/engine/models/event_active_subscriptions.rb +14 -0
- data/lib/splitclient-rb/engine/models/events_metadata.rb +10 -0
- data/lib/splitclient-rb/engine/models/fallback_treatment.rb +11 -0
- data/lib/splitclient-rb/engine/models/fallback_treatments_configuration.rb +36 -0
- data/lib/splitclient-rb/engine/models/label.rb +10 -0
- data/lib/splitclient-rb/engine/models/sdk_event.rb +4 -0
- data/lib/splitclient-rb/engine/models/sdk_event_type.rb +4 -0
- data/lib/splitclient-rb/engine/models/sdk_internal_event.rb +8 -0
- data/lib/splitclient-rb/engine/models/sdk_internal_event_notification.rb +16 -0
- data/lib/splitclient-rb/engine/models/segment_type.rb +4 -0
- data/lib/splitclient-rb/engine/models/split.rb +17 -0
- data/lib/splitclient-rb/engine/models/split_http_response.rb +19 -0
- data/lib/splitclient-rb/engine/models/treatment.rb +3 -0
- data/lib/splitclient-rb/engine/models/valid_sdk_event.rb +14 -0
- data/lib/splitclient-rb/engine/parser/condition.rb +271 -0
- data/lib/splitclient-rb/engine/parser/evaluator.rb +112 -0
- data/lib/{splitclient-engine → splitclient-rb/engine}/parser/partition.rb +2 -4
- data/lib/splitclient-rb/engine/push_manager.rb +66 -0
- data/lib/splitclient-rb/engine/status_manager.rb +39 -0
- data/lib/splitclient-rb/engine/sync_manager.rb +183 -0
- data/lib/splitclient-rb/engine/synchronizer.rb +231 -0
- data/lib/splitclient-rb/exceptions.rb +26 -0
- data/lib/splitclient-rb/helpers/decryption_helper.rb +25 -0
- data/lib/splitclient-rb/helpers/evaluator_helper.rb +37 -0
- data/lib/splitclient-rb/helpers/repository_helper.rb +61 -0
- data/lib/splitclient-rb/helpers/thread_helper.rb +24 -0
- data/lib/splitclient-rb/helpers/util.rb +26 -0
- data/lib/splitclient-rb/managers/split_manager.rb +121 -0
- data/lib/splitclient-rb/spec.rb +9 -0
- data/lib/splitclient-rb/split_config.rb +591 -47
- data/lib/splitclient-rb/split_factory.rb +284 -0
- data/lib/splitclient-rb/split_factory_builder.rb +7 -0
- data/lib/splitclient-rb/split_factory_registry.rb +63 -0
- data/lib/splitclient-rb/split_logger.rb +23 -0
- data/lib/splitclient-rb/sse/event_source/client.rb +264 -0
- data/lib/splitclient-rb/sse/event_source/event_parser.rb +65 -0
- data/lib/splitclient-rb/sse/event_source/event_types.rb +15 -0
- data/lib/splitclient-rb/sse/event_source/stream_data.rb +22 -0
- data/lib/splitclient-rb/sse/notification_manager_keeper.rb +84 -0
- data/lib/splitclient-rb/sse/notification_processor.rb +48 -0
- data/lib/splitclient-rb/sse/sse_handler.rb +44 -0
- data/lib/splitclient-rb/sse/workers/segments_worker.rb +62 -0
- data/lib/splitclient-rb/sse/workers/splits_worker.rb +153 -0
- data/lib/splitclient-rb/telemetry/domain/constants.rb +48 -0
- data/lib/splitclient-rb/telemetry/domain/structs.rb +35 -0
- data/lib/splitclient-rb/telemetry/evaluation_consumer.rb +14 -0
- data/lib/splitclient-rb/telemetry/evaluation_producer.rb +21 -0
- data/lib/splitclient-rb/telemetry/init_consumer.rb +14 -0
- data/lib/splitclient-rb/telemetry/init_producer.rb +19 -0
- data/lib/splitclient-rb/telemetry/memory/memory_evaluation_consumer.rb +32 -0
- data/lib/splitclient-rb/telemetry/memory/memory_evaluation_producer.rb +24 -0
- data/lib/splitclient-rb/telemetry/memory/memory_init_consumer.rb +28 -0
- data/lib/splitclient-rb/telemetry/memory/memory_init_producer.rb +34 -0
- data/lib/splitclient-rb/telemetry/memory/memory_runtime_consumer.rb +119 -0
- data/lib/splitclient-rb/telemetry/memory/memory_runtime_producer.rb +87 -0
- data/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb +213 -0
- data/lib/splitclient-rb/telemetry/redis/redis_evaluation_producer.rb +38 -0
- data/lib/splitclient-rb/telemetry/redis/redis_init_producer.rb +37 -0
- data/lib/splitclient-rb/telemetry/redis/redis_synchronizer.rb +27 -0
- data/lib/splitclient-rb/telemetry/runtime_consumer.rb +25 -0
- data/lib/splitclient-rb/telemetry/runtime_producer.rb +25 -0
- data/lib/splitclient-rb/telemetry/storages/memory.rb +159 -0
- data/lib/splitclient-rb/telemetry/sync_task.rb +36 -0
- data/lib/splitclient-rb/telemetry/synchronizer.rb +33 -0
- data/lib/splitclient-rb/utilitites.rb +49 -0
- data/lib/splitclient-rb/validators.rb +361 -0
- data/lib/splitclient-rb/version.rb +1 -1
- data/lib/splitclient-rb.rb +177 -25
- data/sonar-project.properties +6 -0
- data/splitclient-rb.gemspec +53 -26
- data/tasks/benchmark_get_treatment.rake +31 -17
- data/tasks/irb.rake +6 -0
- metadata +411 -86
- data/NEWS +0 -9
- data/lib/splitclient-cache/local_store.rb +0 -45
- data/lib/splitclient-engine/impressions/impressions.rb +0 -79
- data/lib/splitclient-engine/matchers/between_matcher.rb +0 -48
- data/lib/splitclient-engine/matchers/combining_matcher.rb +0 -94
- data/lib/splitclient-engine/matchers/equal_to_matcher.rb +0 -48
- data/lib/splitclient-engine/matchers/greater_than_or_equal_to_matcher.rb +0 -48
- data/lib/splitclient-engine/matchers/less_than_or_equal_to_matcher.rb +0 -48
- data/lib/splitclient-engine/matchers/negation_matcher.rb +0 -54
- data/lib/splitclient-engine/matchers/user_defined_segment_matcher.rb +0 -61
- data/lib/splitclient-engine/matchers/whitelist_matcher.rb +0 -64
- data/lib/splitclient-engine/metrics/binary_search_latency_tracker.rb +0 -122
- data/lib/splitclient-engine/metrics/metrics.rb +0 -158
- data/lib/splitclient-engine/parser/condition.rb +0 -143
- data/lib/splitclient-engine/parser/segment.rb +0 -84
- data/lib/splitclient-engine/parser/segment_parser.rb +0 -46
- data/lib/splitclient-engine/parser/split.rb +0 -68
- data/lib/splitclient-engine/parser/split_adapter.rb +0 -433
- data/lib/splitclient-engine/parser/split_parser.rb +0 -139
- data/lib/splitclient-engine/partitions/treatments.rb +0 -40
- data/lib/splitclient-rb/split_client.rb +0 -156
- data/lib/splitclient-rb_utilitites.rb +0 -26
- data/tasks/console.rake +0 -4
- data/tasks/rspec.rake +0 -3
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SplitIoClient
|
|
4
|
+
module Engine
|
|
5
|
+
module Common
|
|
6
|
+
class ImpressionManager
|
|
7
|
+
def initialize(config,
|
|
8
|
+
impressions_repository,
|
|
9
|
+
impression_counter,
|
|
10
|
+
telemetry_runtime_producer,
|
|
11
|
+
impression_observer,
|
|
12
|
+
unique_keys_tracker)
|
|
13
|
+
@config = config
|
|
14
|
+
@impressions_repository = impressions_repository
|
|
15
|
+
@impression_counter = impression_counter
|
|
16
|
+
@impression_observer = impression_observer
|
|
17
|
+
@telemetry_runtime_producer = telemetry_runtime_producer
|
|
18
|
+
@unique_keys_tracker = unique_keys_tracker
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def build_impression(matching_key, bucketing_key, split_name, treatment_data, impressions_disabled, params = {},
|
|
22
|
+
evaluation_options = nil)
|
|
23
|
+
properties = get_properties(evaluation_options)
|
|
24
|
+
impression_data = impression_data(matching_key, bucketing_key, split_name, treatment_data, params[:time], properties)
|
|
25
|
+
return impression(impression_data, params[:attributes]) if check_return_conditions(properties)
|
|
26
|
+
|
|
27
|
+
begin
|
|
28
|
+
if check_none_mode(impressions_disabled)
|
|
29
|
+
@impression_counter.inc(split_name, impression_data[:m])
|
|
30
|
+
@unique_keys_tracker.track(split_name, matching_key)
|
|
31
|
+
end
|
|
32
|
+
if check_observe_impressions
|
|
33
|
+
# In DEBUG mode we should calculate the pt only.
|
|
34
|
+
impression_data[:pt] = @impression_observer.test_and_set(impression_data)
|
|
35
|
+
end
|
|
36
|
+
if check_impression_counter(impression_data)
|
|
37
|
+
# In OPTIMIZED mode we should track the total amount of evaluations and deduplicate the impressions.
|
|
38
|
+
@impression_counter.inc(split_name, impression_data[:m])
|
|
39
|
+
end
|
|
40
|
+
rescue StandardError => e
|
|
41
|
+
@config.log_found_exception(__method__.to_s, e)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
impression(impression_data, params[:attributes])
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def track(impressions_decorator)
|
|
48
|
+
return if impressions_decorator.empty?
|
|
49
|
+
|
|
50
|
+
impressions_decorator.each do |impression_decorator|
|
|
51
|
+
impression_router.add_bulk([impression_decorator[:impression]])
|
|
52
|
+
stats = { dropped: 0, queued: 0, dedupe: 0 }
|
|
53
|
+
begin
|
|
54
|
+
next if @config.impressions_mode == :none || impression_decorator[:disabled]
|
|
55
|
+
|
|
56
|
+
if @config.impressions_mode == :debug
|
|
57
|
+
track_debug_mode([impression_decorator[:impression]], stats)
|
|
58
|
+
else
|
|
59
|
+
track_optimized_mode([impression_decorator[:impression]], stats)
|
|
60
|
+
end
|
|
61
|
+
rescue StandardError => e
|
|
62
|
+
@config.log_found_exception(__method__.to_s, e)
|
|
63
|
+
ensure
|
|
64
|
+
record_stats(stats)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def check_return_conditions(properties)
|
|
72
|
+
return (@config.impressions_mode == :debug || @config.impressions_mode == :optimized) && !properties.nil?
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def check_none_mode(impressions_disabled)
|
|
76
|
+
return @config.impressions_mode == :none || impressions_disabled
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def check_observe_impressions
|
|
80
|
+
return @config.impressions_mode == :debug || @config.impressions_mode == :optimized
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def check_impression_counter(impression_data)
|
|
84
|
+
return @config.impressions_mode == :optimized && !impression_data[:pt].nil?
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def get_properties(evaluation_options)
|
|
88
|
+
return evaluation_options.nil? ? nil : evaluation_options.properties
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def impression_router
|
|
92
|
+
@impression_router ||= SplitIoClient::ImpressionRouter.new(@config)
|
|
93
|
+
rescue StandardError => e
|
|
94
|
+
@config.log_found_exception(__method__.to_s, e)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def record_stats(stats)
|
|
98
|
+
return if redis?
|
|
99
|
+
|
|
100
|
+
imp_queued = Telemetry::Domain::Constants::IMPRESSIONS_QUEUED
|
|
101
|
+
imp_dropped = Telemetry::Domain::Constants::IMPRESSIONS_DROPPED
|
|
102
|
+
imp_dedupe = Telemetry::Domain::Constants::IMPRESSIONS_DEDUPE
|
|
103
|
+
@telemetry_runtime_producer.record_impressions_stats(imp_queued, stats[:queued]) unless stats[:queued].zero?
|
|
104
|
+
@telemetry_runtime_producer.record_impressions_stats(imp_dropped, stats[:dropped]) unless stats[:dropped].zero?
|
|
105
|
+
@telemetry_runtime_producer.record_impressions_stats(imp_dedupe, stats[:dedupe]) unless stats[:dedupe].zero?
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# added param time for test
|
|
109
|
+
def impression_data(matching_key, bucketing_key, split_name, treatment, time = nil,
|
|
110
|
+
properties = nil)
|
|
111
|
+
{
|
|
112
|
+
k: matching_key,
|
|
113
|
+
b: bucketing_key,
|
|
114
|
+
f: split_name,
|
|
115
|
+
t: treatment[:treatment],
|
|
116
|
+
r: applied_rule(treatment[:label]),
|
|
117
|
+
c: treatment[:change_number],
|
|
118
|
+
m: time || (Time.now.to_f * 1000.0).to_i,
|
|
119
|
+
pt: nil,
|
|
120
|
+
properties: properties
|
|
121
|
+
}
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def metadata
|
|
125
|
+
{
|
|
126
|
+
s: "#{@config.language}-#{@config.version}",
|
|
127
|
+
i: @config.machine_ip,
|
|
128
|
+
n: @config.machine_name
|
|
129
|
+
}
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def applied_rule(label)
|
|
133
|
+
@config.labels_enabled ? label : nil
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def should_queue_impression?(impression)
|
|
137
|
+
impression[:pt].nil? ||
|
|
138
|
+
(ImpressionCounter.truncate_time_frame(impression[:pt]) != ImpressionCounter.truncate_time_frame(impression[:m]))
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def impression(impression_data, attributes)
|
|
142
|
+
{ m: metadata, i: impression_data, attributes: attributes }
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def redis?
|
|
146
|
+
@config.impressions_adapter.class.to_s == 'SplitIoClient::Cache::Adapters::RedisAdapter'
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def track_debug_mode(impressions, stats)
|
|
150
|
+
stats[:dropped] = @impressions_repository.add_bulk(impressions)
|
|
151
|
+
stats[:queued] = impressions.length - stats[:dropped]
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def track_optimized_mode(impressions, stats)
|
|
155
|
+
optimized_impressions = impressions.select { |imp| should_queue_impression?(imp[:i]) }
|
|
156
|
+
stats[:dedupe] = impressions.length - optimized_impressions.length
|
|
157
|
+
return if optimized_impressions.empty?
|
|
158
|
+
|
|
159
|
+
stats[:dropped] = @impressions_repository.add_bulk(optimized_impressions)
|
|
160
|
+
stats[:queued] = optimized_impressions.length - stats[:dropped]
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'concurrent'
|
|
4
|
+
|
|
5
|
+
module SplitIoClient
|
|
6
|
+
module Engine
|
|
7
|
+
module Common
|
|
8
|
+
class NoopImpressionCounter
|
|
9
|
+
def inc(split_name, time_frame)
|
|
10
|
+
# no-op
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def pop_all
|
|
14
|
+
# no-op
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def make_key(split_name, time_frame)
|
|
18
|
+
# no-op
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.truncate_time_frame(timestamp_ms)
|
|
22
|
+
# no-op
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -4,21 +4,25 @@ module SplitIoClient
|
|
|
4
4
|
# based on provided key
|
|
5
5
|
#
|
|
6
6
|
class Splitter < NoMethodError
|
|
7
|
-
|
|
7
|
+
def initialize
|
|
8
|
+
@murmur_hash = case RUBY_PLATFORM
|
|
9
|
+
when 'java'
|
|
10
|
+
Proc.new { |key, seed| Java::MurmurHash3.murmurhash3_x86_32(key, seed) }
|
|
11
|
+
else
|
|
12
|
+
Proc.new { |key, seed| Digest::MurmurHashMRI3_x86_32.rawdigest(key, [seed].pack('L')) }
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
8
16
|
#
|
|
9
17
|
# Checks if the partiotion size is 100%
|
|
10
18
|
#
|
|
11
19
|
# @param partitions [object] array of partitions
|
|
12
20
|
#
|
|
13
21
|
# @return [boolean] true if partition is 100% false otherwise
|
|
14
|
-
def
|
|
15
|
-
|
|
16
|
-
return false
|
|
17
|
-
end
|
|
18
|
-
return (partitions.first).size == 100
|
|
22
|
+
def hundred_percent_one_treatment?(partitions)
|
|
23
|
+
(partitions.size != 1) ? false : (partitions.first.size == 100)
|
|
19
24
|
end
|
|
20
25
|
|
|
21
|
-
|
|
22
26
|
#
|
|
23
27
|
# gets the appropriate treatment based on id, seed and partition value
|
|
24
28
|
#
|
|
@@ -27,30 +31,41 @@ module SplitIoClient
|
|
|
27
31
|
# @param partitions [object] array of partitions
|
|
28
32
|
#
|
|
29
33
|
# @return traetment [object] treatment value
|
|
30
|
-
def
|
|
34
|
+
def get_treatment(id, seed, partitions, legacy_algo)
|
|
35
|
+
legacy = [1, nil].include?(legacy_algo)
|
|
36
|
+
|
|
31
37
|
if partitions.empty?
|
|
32
|
-
return
|
|
38
|
+
return SplitIoClient::Engine::Models::Treatment::CONTROL
|
|
33
39
|
end
|
|
34
40
|
|
|
35
41
|
if hundred_percent_one_treatment?(partitions)
|
|
36
42
|
return (partitions.first).treatment
|
|
37
43
|
end
|
|
38
44
|
|
|
39
|
-
return get_treatment_for_key(bucket(
|
|
45
|
+
return get_treatment_for_key(bucket(count_hash(id, seed, legacy)), partitions)
|
|
40
46
|
end
|
|
41
47
|
|
|
48
|
+
# returns a hash value for the give key, seed pair
|
|
42
49
|
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
# @param key [string] user key
|
|
46
|
-
# @param seed [number] seed for the user key
|
|
50
|
+
# @param key [String] user key
|
|
51
|
+
# @param seed [Fixnum] seed for the user key
|
|
47
52
|
#
|
|
48
|
-
# @return hash [
|
|
49
|
-
def
|
|
53
|
+
# @return hash [String] hash value
|
|
54
|
+
def count_hash(key, seed, legacy)
|
|
55
|
+
legacy ? legacy_hash(key, seed) : murmur_hash(key, seed)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def murmur_hash(key, seed)
|
|
59
|
+
@murmur_hash.call(key, seed)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def legacy_hash(key, seed)
|
|
50
63
|
h = 0
|
|
64
|
+
|
|
51
65
|
for i in 0..key.length-1
|
|
52
66
|
h = to_int32(31 * h + key[i].ord)
|
|
53
67
|
end
|
|
68
|
+
|
|
54
69
|
h^seed
|
|
55
70
|
end
|
|
56
71
|
|
|
@@ -60,7 +75,7 @@ module SplitIoClient
|
|
|
60
75
|
# @param number [number] ruby number value
|
|
61
76
|
#
|
|
62
77
|
# @return [int] returns the int 32 value of the provided number
|
|
63
|
-
def
|
|
78
|
+
def to_int32(number)
|
|
64
79
|
begin
|
|
65
80
|
sign = number < 0 ? -1 : 1
|
|
66
81
|
abs = number.abs
|
|
@@ -83,7 +98,7 @@ module SplitIoClient
|
|
|
83
98
|
# @param parittions [object] array of partitions
|
|
84
99
|
#
|
|
85
100
|
# @return treatment [treatment] treatment value for this bucket and partitions
|
|
86
|
-
def
|
|
101
|
+
def get_treatment_for_key(bucket, partitions)
|
|
87
102
|
buckets_covered_thus_far = 0
|
|
88
103
|
partitions.each do |p|
|
|
89
104
|
unless p.is_empty?
|
|
@@ -92,7 +107,7 @@ module SplitIoClient
|
|
|
92
107
|
end
|
|
93
108
|
end
|
|
94
109
|
|
|
95
|
-
return
|
|
110
|
+
return SplitIoClient::Engine::Models::Treatment::CONTROL
|
|
96
111
|
end
|
|
97
112
|
|
|
98
113
|
#
|
|
@@ -101,10 +116,8 @@ module SplitIoClient
|
|
|
101
116
|
# @param hash_value [string] hash value
|
|
102
117
|
#
|
|
103
118
|
# @return bucket [number] bucket number
|
|
104
|
-
def
|
|
119
|
+
def bucket(hash_value)
|
|
105
120
|
(hash_value.abs % 100) + 1
|
|
106
121
|
end
|
|
107
|
-
|
|
108
122
|
end
|
|
109
|
-
|
|
110
123
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SplitIoClient
|
|
4
|
+
module Engine
|
|
5
|
+
module Events
|
|
6
|
+
class EventsDelivery
|
|
7
|
+
def initialize(config)
|
|
8
|
+
@config = config
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def deliver(sdk_event, event_metadata, event_handler)
|
|
12
|
+
event_handler.call(event_metadata)
|
|
13
|
+
rescue StandardError => e
|
|
14
|
+
@config.logger.error("Exception when calling handler for Sdk Event #{sdk_event}")
|
|
15
|
+
@config.log_found_exception(__method__.to_s, e)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SplitIoClient
|
|
4
|
+
module Engine
|
|
5
|
+
module Events
|
|
6
|
+
class EventsManager
|
|
7
|
+
def initialize(events_manager_config, events_delivery, config)
|
|
8
|
+
@manager_config = events_manager_config
|
|
9
|
+
@events_delivery = events_delivery
|
|
10
|
+
@active_subscriptions = {}
|
|
11
|
+
@internal_events_status = {}
|
|
12
|
+
@mutex = Mutex.new
|
|
13
|
+
@config = config
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def register(sdk_event, event_handler)
|
|
17
|
+
return if @active_subscriptions.key?(sdk_event) && !get_event_handler(sdk_event).nil?
|
|
18
|
+
|
|
19
|
+
@mutex.synchronize do
|
|
20
|
+
# SDK ready already fired
|
|
21
|
+
if sdk_event == Engine::Models::SdkEvent::SDK_READY && event_already_triggered(sdk_event)
|
|
22
|
+
@active_subscriptions[sdk_event] = Engine::Models::EventActiveSubscriptions.new(true, event_handler)
|
|
23
|
+
@config.logger.debug('EventsManager: Firing SDK_READY event for new subscription') if @config.debug_enabled
|
|
24
|
+
fire_sdk_event(sdk_event, nil)
|
|
25
|
+
return
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
@config.logger.debug("EventsManager: Register event: #{sdk_event}") if @config.debug_enabled
|
|
29
|
+
@active_subscriptions[sdk_event] = Engine::Models::EventActiveSubscriptions.new(false, event_handler)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def unregister(sdk_event)
|
|
34
|
+
return unless @active_subscriptions.key?(sdk_event)
|
|
35
|
+
|
|
36
|
+
@mutex.synchronize do
|
|
37
|
+
@active_subscriptions.delete(sdk_event)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def notify_internal_event(sdk_internal_event, event_metadata)
|
|
42
|
+
@mutex.synchronize do
|
|
43
|
+
update_internal_event_status(sdk_internal_event, true)
|
|
44
|
+
@manager_config.evaluation_order.each do |sorted_event|
|
|
45
|
+
if get_sdk_event_if_applicable(sdk_internal_event).include?(sorted_event) &&
|
|
46
|
+
!get_event_handler(sorted_event).nil?
|
|
47
|
+
fire_sdk_event(sorted_event, event_metadata)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# if client is not subscribed to SDK_READY
|
|
51
|
+
if check_if_register_needed(sorted_event)
|
|
52
|
+
@config.logger.debug('EventsManager: Registering SDK_READY event as fired') if @config.debug_enabled
|
|
53
|
+
@active_subscriptions[Engine::Models::SdkEvent::SDK_READY] = Engine::Models::EventActiveSubscriptions.new(true, nil)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def destroy
|
|
60
|
+
@mutex.synchronize do
|
|
61
|
+
@active_subscriptions = {}
|
|
62
|
+
@internal_events_status = {}
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private
|
|
67
|
+
|
|
68
|
+
def check_if_register_needed(sorted_event)
|
|
69
|
+
sorted_event == Engine::Models::SdkEvent::SDK_READY &&
|
|
70
|
+
get_event_handler(sorted_event).nil? &&
|
|
71
|
+
!@active_subscriptions.include?(sorted_event)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def fire_sdk_event(sdk_event, event_metadata)
|
|
75
|
+
@config.logger.debug("EventsManager: Firing Sdk event: #{sdk_event}") if @config.debug_enabled
|
|
76
|
+
@config.threads[:sdk_event_notify] = Thread.new do
|
|
77
|
+
@events_delivery.deliver(sdk_event, event_metadata, get_event_handler(sdk_event))
|
|
78
|
+
end
|
|
79
|
+
sdk_event_triggered(sdk_event)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def event_already_triggered(sdk_event)
|
|
83
|
+
return @active_subscriptions[sdk_event].triggered if @active_subscriptions.key?(sdk_event)
|
|
84
|
+
|
|
85
|
+
false
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def get_internal_event_status(sdk_internal_event)
|
|
89
|
+
return @internal_events_status[sdk_internal_event] if @internal_events_status.key?(sdk_internal_event)
|
|
90
|
+
|
|
91
|
+
false
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def update_internal_event_status(sdk_internal_event, status)
|
|
95
|
+
@internal_events_status[sdk_internal_event] = status
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def sdk_event_triggered(sdk_event)
|
|
99
|
+
return unless @active_subscriptions.key?(sdk_event)
|
|
100
|
+
|
|
101
|
+
return if @active_subscriptions[sdk_event].triggered
|
|
102
|
+
|
|
103
|
+
@active_subscriptions[sdk_event].triggered = true
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def get_event_handler(sdk_event)
|
|
107
|
+
return nil unless @active_subscriptions.key?(sdk_event)
|
|
108
|
+
|
|
109
|
+
@active_subscriptions[sdk_event].handler
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def get_sdk_event_if_applicable(sdk_internal_event)
|
|
113
|
+
final_sdk_event = Engine::Models::ValidSdkEvent.new(nil, false)
|
|
114
|
+
|
|
115
|
+
events_to_fire = []
|
|
116
|
+
require_any_sdk_event = check_require_any(sdk_internal_event)
|
|
117
|
+
if require_any_sdk_event.valid
|
|
118
|
+
if (!event_already_triggered(require_any_sdk_event.sdk_event) &&
|
|
119
|
+
execution_limit(require_any_sdk_event.sdk_event) == 1) ||
|
|
120
|
+
execution_limit(require_any_sdk_event.sdk_event) == -1
|
|
121
|
+
final_sdk_event = Engine::Models::ValidSdkEvent.new(
|
|
122
|
+
require_any_sdk_event.sdk_event,
|
|
123
|
+
check_prerequisites(require_any_sdk_event.sdk_event) &&
|
|
124
|
+
check_suppressed_by(require_any_sdk_event.sdk_event)
|
|
125
|
+
)
|
|
126
|
+
end
|
|
127
|
+
events_to_fire.push(final_sdk_event.sdk_event) if final_sdk_event.valid
|
|
128
|
+
end
|
|
129
|
+
check_require_all.each { |sdk_event| events_to_fire.push(sdk_event) }
|
|
130
|
+
|
|
131
|
+
events_to_fire
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def check_require_all
|
|
135
|
+
events = []
|
|
136
|
+
@manager_config.require_all.each do |require_name, require_value|
|
|
137
|
+
final_status = true
|
|
138
|
+
require_value.each { |val| final_status &= get_internal_event_status(val) }
|
|
139
|
+
events.push(require_name) if check_event_eligible_conditions(final_status, require_name, require_value)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
events
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def check_event_eligible_conditions(final_status, require_name, require_value)
|
|
146
|
+
final_status &&
|
|
147
|
+
check_prerequisites(require_name) &&
|
|
148
|
+
((!event_already_triggered(require_name) &&
|
|
149
|
+
execution_limit(require_name) == 1) ||
|
|
150
|
+
execution_limit(require_name) == -1) &&
|
|
151
|
+
require_value.length.positive?
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def check_prerequisites(sdk_event)
|
|
155
|
+
@manager_config.prerequisites.each do |name, value|
|
|
156
|
+
value.each do |val|
|
|
157
|
+
return false if name == sdk_event && !event_already_triggered(val)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
true
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def check_suppressed_by(sdk_event)
|
|
165
|
+
@manager_config.suppressed_by.each do |name, value|
|
|
166
|
+
value.each do |val|
|
|
167
|
+
return false if name == sdk_event && event_already_triggered(val)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
true
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def execution_limit(sdk_event)
|
|
175
|
+
return -1 unless @manager_config.execution_limits.key?(sdk_event)
|
|
176
|
+
|
|
177
|
+
@manager_config.execution_limits[sdk_event]
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def check_require_any(sdk_internal_event)
|
|
181
|
+
valid_sdk_event = Engine::Models::ValidSdkEvent.new(nil, false)
|
|
182
|
+
@manager_config.require_any.each do |name, val|
|
|
183
|
+
if val.include?(sdk_internal_event)
|
|
184
|
+
valid_sdk_event = Engine::Models::ValidSdkEvent.new(name, true)
|
|
185
|
+
return valid_sdk_event
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
valid_sdk_event
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SplitIoClient
|
|
4
|
+
module Engine
|
|
5
|
+
module Events
|
|
6
|
+
class EventsManagerConfig
|
|
7
|
+
attr_accessor :require_all, :prerequisites, :require_any, :suppressed_by, :execution_limits, :evaluation_order
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
@require_all = construct_require_all
|
|
11
|
+
@prerequisites = construct_prerequisites
|
|
12
|
+
@require_any = construct_require_any
|
|
13
|
+
@suppressed_by = construct_suppressed_by
|
|
14
|
+
@execution_limits = construct_execution_limits
|
|
15
|
+
@evaluation_order = construct_sorted_events
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
def construct_require_all
|
|
21
|
+
{
|
|
22
|
+
SplitIoClient::Engine::Models::SdkEvent::SDK_READY => Set.new([SplitIoClient::Engine::Models::SdkInternalEvent::SDK_READY])
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def construct_prerequisites
|
|
27
|
+
{
|
|
28
|
+
SplitIoClient::Engine::Models::SdkEvent::SDK_UPDATE => Set.new([SplitIoClient::Engine::Models::SdkEvent::SDK_READY])
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def construct_require_any
|
|
33
|
+
{
|
|
34
|
+
SplitIoClient::Engine::Models::SdkEvent::SDK_UPDATE => Set.new(
|
|
35
|
+
[
|
|
36
|
+
SplitIoClient::Engine::Models::SdkInternalEvent::FLAG_KILLED_NOTIFICATION,
|
|
37
|
+
SplitIoClient::Engine::Models::SdkInternalEvent::FLAGS_UPDATED,
|
|
38
|
+
SplitIoClient::Engine::Models::SdkInternalEvent::RB_SEGMENTS_UPDATED,
|
|
39
|
+
SplitIoClient::Engine::Models::SdkInternalEvent::SEGMENTS_UPDATED
|
|
40
|
+
]
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def construct_suppressed_by
|
|
46
|
+
{}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def construct_execution_limits
|
|
50
|
+
{
|
|
51
|
+
SplitIoClient::Engine::Models::SdkEvent::SDK_READY => 1,
|
|
52
|
+
SplitIoClient::Engine::Models::SdkEvent::SDK_UPDATE => -1
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def construct_sorted_events
|
|
57
|
+
sorted_events = []
|
|
58
|
+
[SplitIoClient::Engine::Models::SdkEvent::SDK_READY, SplitIoClient::Engine::Models::SdkEvent::SDK_UPDATE].each do |sdk_event|
|
|
59
|
+
sorted_events = dfs_recursive(sdk_event, sorted_events)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
sorted_events
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def dfs_recursive(sdk_event, added)
|
|
66
|
+
return added if added.include?(sdk_event)
|
|
67
|
+
|
|
68
|
+
get_dependencies(sdk_event).each do |dependent_event|
|
|
69
|
+
added = dfs_recursive(dependent_event, added)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
added.push(sdk_event)
|
|
73
|
+
|
|
74
|
+
added
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def get_dependencies(sdk_event)
|
|
78
|
+
dependencies = Set.new
|
|
79
|
+
@prerequisites.each do |prerequisites_event_name, prerequisites_event_value|
|
|
80
|
+
next unless prerequisites_event_name == sdk_event
|
|
81
|
+
|
|
82
|
+
prerequisites_event_value.each do |prereq_event|
|
|
83
|
+
dependencies.add(prereq_event)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
@suppressed_by.each do |suppressed_event_name, suppressed_event_value|
|
|
88
|
+
dependencies.add(suppressed_event_name) if suppressed_event_value.include?(sdk_event)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
dependencies
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SplitIoClient
|
|
4
|
+
module Engine
|
|
5
|
+
module Events
|
|
6
|
+
class EventsTask
|
|
7
|
+
attr_accessor :running
|
|
8
|
+
|
|
9
|
+
def initialize(notify_internal_events, internal_events_queue, config)
|
|
10
|
+
@notify_internal_events = notify_internal_events
|
|
11
|
+
@internal_events_queue = internal_events_queue
|
|
12
|
+
@config = config
|
|
13
|
+
@running = false
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def start
|
|
17
|
+
return if @running
|
|
18
|
+
|
|
19
|
+
@config.logger.info('Starting Internal Events Task.')
|
|
20
|
+
@running = true
|
|
21
|
+
@config.threads[:internal_events_task] = Thread.new do
|
|
22
|
+
worker_thread
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def stop
|
|
27
|
+
return unless @running
|
|
28
|
+
|
|
29
|
+
@config.logger.info('Stopping Internal Events Task.')
|
|
30
|
+
@running = false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def worker_thread
|
|
36
|
+
while (event = @internal_events_queue.pop)
|
|
37
|
+
break unless @running
|
|
38
|
+
|
|
39
|
+
@config.logger.debug("Processing sdk internal event: #{event.internal_event}") if @config.debug_enabled
|
|
40
|
+
begin
|
|
41
|
+
@notify_internal_events.call(event.internal_event, event.metadata)
|
|
42
|
+
rescue StandardError => e
|
|
43
|
+
@config.log_found_exception(__method__.to_s, e)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|