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
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
require 'thread_safe'
|
|
2
|
-
|
|
3
|
-
module SplitIoClient
|
|
4
|
-
# A thread-safe in-memory store suitable for use
|
|
5
|
-
# with the Faraday caching HTTP client, uses the
|
|
6
|
-
# Threadsafe gem as the underlying cache.
|
|
7
|
-
#
|
|
8
|
-
class LocalStore
|
|
9
|
-
#
|
|
10
|
-
# Default constructor
|
|
11
|
-
#
|
|
12
|
-
# @return [ThreadSafeMemoryStore] a new store
|
|
13
|
-
def initialize
|
|
14
|
-
@cache = ThreadSafe::Cache.new
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
#
|
|
18
|
-
# Read a value from the cache
|
|
19
|
-
# @param key [Object] the cache key
|
|
20
|
-
#
|
|
21
|
-
# @return [Object] the cache value
|
|
22
|
-
def read(key)
|
|
23
|
-
@cache[key]
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
#
|
|
27
|
-
# Store a value in the cache
|
|
28
|
-
# @param key [Object] the cache key
|
|
29
|
-
# @param value [Object] the value to associate with the key
|
|
30
|
-
#
|
|
31
|
-
# @return [Object] the value
|
|
32
|
-
def write(key, value)
|
|
33
|
-
@cache[key] = value
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
# deletes value from cache by given key
|
|
38
|
-
# @param key [Object] the cache key
|
|
39
|
-
def delete(key)
|
|
40
|
-
@cache[key] = nil
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
end
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
# class to manage cached impressions
|
|
5
|
-
#
|
|
6
|
-
class Impressions < NoMethodError
|
|
7
|
-
|
|
8
|
-
# the queue of cached impression values
|
|
9
|
-
#
|
|
10
|
-
# @return [object] array of impressions
|
|
11
|
-
attr_accessor :queue
|
|
12
|
-
|
|
13
|
-
# max number of cached entries for impressions
|
|
14
|
-
#
|
|
15
|
-
# @return [int] max numbre of entries
|
|
16
|
-
attr_accessor :max_number_of_keys
|
|
17
|
-
|
|
18
|
-
#
|
|
19
|
-
# initializes the class
|
|
20
|
-
#
|
|
21
|
-
# @param max [int] max number of cached entries
|
|
22
|
-
def initialize(max)
|
|
23
|
-
@queue = Queue.new
|
|
24
|
-
@max_number_of_keys = max
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
#
|
|
28
|
-
# generates a new entry for impressions list
|
|
29
|
-
#
|
|
30
|
-
# @param id [string] user key
|
|
31
|
-
# @param feature [string] feature name
|
|
32
|
-
# @param treatment [string] treatment value
|
|
33
|
-
# @param time [time] time value in milisenconds
|
|
34
|
-
#
|
|
35
|
-
# @return void
|
|
36
|
-
def log(id, feature, treatment, time)
|
|
37
|
-
impressions = KeyImpressions.new(id, treatment, time)
|
|
38
|
-
@queue << {feature: feature, impressions: impressions}
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
#
|
|
42
|
-
# clears the impressions queue
|
|
43
|
-
#
|
|
44
|
-
# @returns void
|
|
45
|
-
def clear
|
|
46
|
-
popped_impressions = []
|
|
47
|
-
begin
|
|
48
|
-
loop do
|
|
49
|
-
impression_element = @queue.pop(true)
|
|
50
|
-
feature_hash = popped_impressions.find { |i| i[:feature] == impression_element[:feature] }
|
|
51
|
-
if feature_hash.nil?
|
|
52
|
-
popped_impressions << {feature: impression_element[:feature], impressions: [] << impression_element[:impressions]}
|
|
53
|
-
else
|
|
54
|
-
feature_hash[:impressions] << impression_element[:impressions]
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
rescue ThreadError
|
|
58
|
-
end
|
|
59
|
-
popped_impressions
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
#
|
|
65
|
-
# small class to use as DTO for impressions
|
|
66
|
-
#
|
|
67
|
-
class KeyImpressions
|
|
68
|
-
attr_accessor :key
|
|
69
|
-
attr_accessor :treatment
|
|
70
|
-
attr_accessor :time
|
|
71
|
-
|
|
72
|
-
def initialize(key, treatment, time)
|
|
73
|
-
@key = key
|
|
74
|
-
@treatment = treatment
|
|
75
|
-
@time = time
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
end
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
|
|
3
|
-
class BetweenMatcher < NoMethodError
|
|
4
|
-
|
|
5
|
-
attr_reader :matcher_type
|
|
6
|
-
|
|
7
|
-
def initialize(attribute_hash)
|
|
8
|
-
@matcher_type = "BETWEEN"
|
|
9
|
-
@attribute = attribute_hash[:attribute]
|
|
10
|
-
@start_value = attribute_hash[:start_value]
|
|
11
|
-
@end_value = attribute_hash[:end_value]
|
|
12
|
-
@data_type = attribute_hash[:data_type]
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def match?(attributes)
|
|
16
|
-
matches = false
|
|
17
|
-
if (!attributes.nil? && attributes.key?(@attribute.to_sym))
|
|
18
|
-
param_value = get_formatted_value(attributes[@attribute.to_sym])
|
|
19
|
-
matches = ((param_value >= @start_value) && (param_value <= @end_value))
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def equals?(obj)
|
|
24
|
-
if obj.nil?
|
|
25
|
-
false
|
|
26
|
-
elsif !obj.instance_of?(BetweenMatcher)
|
|
27
|
-
false
|
|
28
|
-
elsif self.equal?(obj)
|
|
29
|
-
true
|
|
30
|
-
else
|
|
31
|
-
false
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
private
|
|
36
|
-
def get_formatted_value(value)
|
|
37
|
-
case @data_type
|
|
38
|
-
when "NUMBER"
|
|
39
|
-
return value
|
|
40
|
-
when "DATETIME"
|
|
41
|
-
return ::Utilities.to_milis_zero_out_from_seconds value
|
|
42
|
-
else
|
|
43
|
-
@logger.error('Invalid data type')
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
end
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
require 'splitclient-engine/matchers/combiners'
|
|
2
|
-
|
|
3
|
-
module SplitIoClient
|
|
4
|
-
#
|
|
5
|
-
# class to implement the combining matcher
|
|
6
|
-
#
|
|
7
|
-
class CombiningMatcher < NoMethodError
|
|
8
|
-
|
|
9
|
-
#
|
|
10
|
-
# list of matcher within the combiner
|
|
11
|
-
#
|
|
12
|
-
@matcher_list = []
|
|
13
|
-
|
|
14
|
-
#
|
|
15
|
-
# combiner value
|
|
16
|
-
#
|
|
17
|
-
@combiner = ''
|
|
18
|
-
|
|
19
|
-
def initialize(combiner, delegates)
|
|
20
|
-
unless delegates.nil?
|
|
21
|
-
@matcher_list = delegates
|
|
22
|
-
end
|
|
23
|
-
unless combiner.nil?
|
|
24
|
-
@combiner = combiner
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
#
|
|
29
|
-
# evaluates if the key matches the matchers within the combiner
|
|
30
|
-
#
|
|
31
|
-
# @param key [string] key value to be matched
|
|
32
|
-
#
|
|
33
|
-
# @return [boolean] match value for combiner delegates
|
|
34
|
-
def match?(key)
|
|
35
|
-
if @matcher_list.empty?
|
|
36
|
-
return false
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
case @combiner
|
|
40
|
-
when Combiners::AND
|
|
41
|
-
return and_eval(key)
|
|
42
|
-
else
|
|
43
|
-
#throws error
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
#
|
|
48
|
-
# auxiliary method to evaluate each of the matchers within the combiner
|
|
49
|
-
#
|
|
50
|
-
# @param key [string] key value to be matched
|
|
51
|
-
#
|
|
52
|
-
# @return [boolean] match value for combiner delegates
|
|
53
|
-
def and_eval(key)
|
|
54
|
-
result = true
|
|
55
|
-
@matcher_list.each do |delegate|
|
|
56
|
-
result &= (delegate.match?(key))
|
|
57
|
-
end
|
|
58
|
-
result
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
#
|
|
62
|
-
# evaluates if the given object equals the matcher
|
|
63
|
-
#
|
|
64
|
-
# @param obj [object] object to be evaluated
|
|
65
|
-
#
|
|
66
|
-
# @returns [boolean] true if obj equals the matcher
|
|
67
|
-
def equals?(obj)
|
|
68
|
-
if obj.nil?
|
|
69
|
-
false
|
|
70
|
-
elsif !obj.instance_of?(CombiningMatcher)
|
|
71
|
-
false
|
|
72
|
-
elsif self.equal?(obj)
|
|
73
|
-
true
|
|
74
|
-
else
|
|
75
|
-
false
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
#
|
|
80
|
-
# function to print string value for this matcher
|
|
81
|
-
#
|
|
82
|
-
# @reutrn [string] string value of this matcher
|
|
83
|
-
def to_s
|
|
84
|
-
result = ''
|
|
85
|
-
@matcher_list.each_with_index do |matcher, i|
|
|
86
|
-
result += matcher.to_s
|
|
87
|
-
result += ' ' + @combiner if i != 0
|
|
88
|
-
end
|
|
89
|
-
result
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
end
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
|
|
3
|
-
class EqualToMatcher < NoMethodError
|
|
4
|
-
|
|
5
|
-
attr_reader :matcher_type
|
|
6
|
-
|
|
7
|
-
def initialize(attribute_hash)
|
|
8
|
-
@matcher_type = "EQUAL_TO"
|
|
9
|
-
@attribute = attribute_hash[:attribute]
|
|
10
|
-
@value = attribute_hash[:value]
|
|
11
|
-
@data_type = attribute_hash[:data_type]
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def match?(attributes)
|
|
15
|
-
matches = false
|
|
16
|
-
if (!attributes.nil? && attributes.key?(@attribute.to_sym))
|
|
17
|
-
param_value = get_formatted_value(attributes[@attribute.to_sym])
|
|
18
|
-
matches = (param_value == @value)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def equals?(obj)
|
|
23
|
-
if obj.nil?
|
|
24
|
-
false
|
|
25
|
-
elsif !obj.instance_of?(EqualToMatcher)
|
|
26
|
-
false
|
|
27
|
-
elsif self.equal?(obj)
|
|
28
|
-
true
|
|
29
|
-
else
|
|
30
|
-
false
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
private
|
|
35
|
-
def get_formatted_value(value)
|
|
36
|
-
case @data_type
|
|
37
|
-
when "NUMBER"
|
|
38
|
-
return value
|
|
39
|
-
when "DATETIME"
|
|
40
|
-
return ::Utilities.to_milis_zero_out_from_hour value
|
|
41
|
-
else
|
|
42
|
-
@logger.error('Invalid data type')
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
end
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
|
|
3
|
-
class GreaterThanOrEqualToMatcher < NoMethodError
|
|
4
|
-
|
|
5
|
-
attr_reader :matcher_type
|
|
6
|
-
|
|
7
|
-
def initialize(attribute_hash)
|
|
8
|
-
@matcher_type = "GREATER_THAN_OR_EQUAL_TO"
|
|
9
|
-
@attribute = attribute_hash[:attribute]
|
|
10
|
-
@value = attribute_hash[:value]
|
|
11
|
-
@data_type = attribute_hash[:data_type]
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def match?(attributes)
|
|
15
|
-
matches = false
|
|
16
|
-
if (!attributes.nil? && attributes.key?(@attribute.to_sym))
|
|
17
|
-
param_value = get_formatted_value(attributes[@attribute.to_sym])
|
|
18
|
-
matches = (param_value >= @value)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def equals?(obj)
|
|
23
|
-
if obj.nil?
|
|
24
|
-
false
|
|
25
|
-
elsif !obj.instance_of?(GreaterThanOrEqualToMatcher)
|
|
26
|
-
false
|
|
27
|
-
elsif self.equal?(obj)
|
|
28
|
-
true
|
|
29
|
-
else
|
|
30
|
-
false
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
private
|
|
35
|
-
def get_formatted_value(value)
|
|
36
|
-
case @data_type
|
|
37
|
-
when "NUMBER"
|
|
38
|
-
return value
|
|
39
|
-
when "DATETIME"
|
|
40
|
-
return ::Utilities.to_milis_zero_out_from_seconds value
|
|
41
|
-
else
|
|
42
|
-
@logger.error('Invalid data type')
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
end
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
|
|
3
|
-
class LessThanOrEqualToMatcher < NoMethodError
|
|
4
|
-
|
|
5
|
-
attr_reader :matcher_type
|
|
6
|
-
|
|
7
|
-
def initialize(attribute_hash)
|
|
8
|
-
@matcher_type = "LESS_THAN_OR_EQUAL_TO"
|
|
9
|
-
@attribute = attribute_hash[:attribute]
|
|
10
|
-
@value = attribute_hash[:value]
|
|
11
|
-
@data_type = attribute_hash[:data_type]
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def match?(attributes)
|
|
15
|
-
matches = false
|
|
16
|
-
if (!attributes.nil? && attributes.key?(@attribute.to_sym))
|
|
17
|
-
param_value = get_formatted_value(attributes[@attribute.to_sym])
|
|
18
|
-
matches = (param_value <= @value)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def equals?(obj)
|
|
23
|
-
if obj.nil?
|
|
24
|
-
false
|
|
25
|
-
elsif !obj.instance_of?(LessThanOrEqualToMatcher)
|
|
26
|
-
false
|
|
27
|
-
elsif self.equal?(obj)
|
|
28
|
-
true
|
|
29
|
-
else
|
|
30
|
-
false
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
private
|
|
35
|
-
def get_formatted_value(value)
|
|
36
|
-
case @data_type
|
|
37
|
-
when "NUMBER"
|
|
38
|
-
return value
|
|
39
|
-
when "DATETIME"
|
|
40
|
-
return ::Utilities.to_milis_zero_out_from_seconds value
|
|
41
|
-
else
|
|
42
|
-
@logger.error('Invalid data type')
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
end
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
# class to implement the negation of a matcher
|
|
5
|
-
#
|
|
6
|
-
class NegationMatcher < NoMethodError
|
|
7
|
-
|
|
8
|
-
@matcher = nil
|
|
9
|
-
|
|
10
|
-
def initialize(matcher)
|
|
11
|
-
unless matcher.nil?
|
|
12
|
-
@matcher = matcher
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
#
|
|
17
|
-
# evaluates if the key matches the negation of the matcher
|
|
18
|
-
#
|
|
19
|
-
# @param key [string] key value to be matched
|
|
20
|
-
#
|
|
21
|
-
# @return [boolean] evaluation of the negation matcher
|
|
22
|
-
def match?(key)
|
|
23
|
-
!@matcher.match?(key)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
#
|
|
27
|
-
# evaluates if the given object equals the matcher
|
|
28
|
-
#
|
|
29
|
-
# @param obj [object] object to be evaluated
|
|
30
|
-
#
|
|
31
|
-
# @returns [boolean] true if obj equals the matcher
|
|
32
|
-
def equals?(obj)
|
|
33
|
-
if obj.nil?
|
|
34
|
-
false
|
|
35
|
-
elsif !obj.instance_of?(NegationMatcher)
|
|
36
|
-
false
|
|
37
|
-
elsif self.equal?(obj)
|
|
38
|
-
true
|
|
39
|
-
else
|
|
40
|
-
false
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
#
|
|
45
|
-
# function to print string value for this matcher
|
|
46
|
-
#
|
|
47
|
-
# @reutrn [string] string value of this matcher
|
|
48
|
-
def to_s
|
|
49
|
-
'not ' + @matcher.to_s
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
end
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
# class to implement the user defined matcher
|
|
5
|
-
#
|
|
6
|
-
class UserDefinedSegmentMatcher < NoMethodError
|
|
7
|
-
|
|
8
|
-
attr_reader :matcher_type
|
|
9
|
-
|
|
10
|
-
@segment = nil
|
|
11
|
-
|
|
12
|
-
def initialize(segment)
|
|
13
|
-
@matcher_type = "IN_SEGMENT"
|
|
14
|
-
unless segment.nil?
|
|
15
|
-
@segment = segment
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
#
|
|
20
|
-
# evaluates if the key matches the matcher
|
|
21
|
-
#
|
|
22
|
-
# @param key [string] key value to be matched
|
|
23
|
-
#
|
|
24
|
-
# @return [boolean] evaluation of the key against the segment
|
|
25
|
-
def match?(key)
|
|
26
|
-
matches = false
|
|
27
|
-
unless @segment.users.nil?
|
|
28
|
-
matches = @segment.users.include?(key)
|
|
29
|
-
end
|
|
30
|
-
matches
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
#
|
|
34
|
-
# evaluates if the given object equals the matcher
|
|
35
|
-
#
|
|
36
|
-
# @param obj [object] object to be evaluated
|
|
37
|
-
#
|
|
38
|
-
# @returns [boolean] true if obj equals the matcher
|
|
39
|
-
def equals?(obj)
|
|
40
|
-
if obj.nil?
|
|
41
|
-
false
|
|
42
|
-
elsif !obj.instance_of?(UserDefinedSegmentMatcher)
|
|
43
|
-
false
|
|
44
|
-
elsif self.equal?(obj)
|
|
45
|
-
true
|
|
46
|
-
else
|
|
47
|
-
false
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
#
|
|
52
|
-
# function to print string value for this matcher
|
|
53
|
-
#
|
|
54
|
-
# @reutrn [string] string value of this matcher
|
|
55
|
-
def to_s
|
|
56
|
-
'in segment ' + @segment.name
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
end
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
# class to implement the user defined matcher
|
|
5
|
-
#
|
|
6
|
-
class WhitelistMatcher < NoMethodError
|
|
7
|
-
|
|
8
|
-
attr_reader :matcher_type
|
|
9
|
-
|
|
10
|
-
# variable that contains the keys of the whitelist
|
|
11
|
-
@whitelist = []
|
|
12
|
-
|
|
13
|
-
def initialize(whitelist_data)
|
|
14
|
-
if whitelist_data.instance_of? Array
|
|
15
|
-
@whitelist = whitelist_data unless whitelist_data.nil?
|
|
16
|
-
elsif whitelist_data.instance_of? Hash
|
|
17
|
-
@matcher_type = "ATTR_WHITELIST"
|
|
18
|
-
@attribute = whitelist_data[:attribute]
|
|
19
|
-
@whitelist = whitelist_data[:value] unless whitelist_data[:value].nil?
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def match?(whitelist_data)
|
|
24
|
-
matches = false
|
|
25
|
-
if !(@matcher_type == "ATTR_WHITELIST")
|
|
26
|
-
matches = @whitelist.include?(whitelist_data)
|
|
27
|
-
else
|
|
28
|
-
if (!whitelist_data.nil? && whitelist_data.key?(@attribute.to_sym))
|
|
29
|
-
value = whitelist_data[@attribute.to_sym]
|
|
30
|
-
matches = @whitelist.include?(value)
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
matches
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
#
|
|
37
|
-
# evaluates if the given object equals the matcher
|
|
38
|
-
#
|
|
39
|
-
# @param obj [object] object to be evaluated
|
|
40
|
-
#
|
|
41
|
-
# @returns [boolean] true if obj equals the matcher
|
|
42
|
-
def equals?(obj)
|
|
43
|
-
if obj.nil?
|
|
44
|
-
false
|
|
45
|
-
elsif !obj.instance_of?(WhitelistMatcher)
|
|
46
|
-
false
|
|
47
|
-
elsif self.equal?(obj)
|
|
48
|
-
true
|
|
49
|
-
else
|
|
50
|
-
false
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
#
|
|
55
|
-
# function to print string value for this matcher
|
|
56
|
-
#
|
|
57
|
-
# @reutrn [string] string value of this matcher
|
|
58
|
-
def to_s
|
|
59
|
-
'in segment ' + @whitelist.to_s
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
end
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
module SplitIoClient
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
# Tracks latencies pero bucket of time.
|
|
5
|
-
# Each bucket represent a latency greater than the one before
|
|
6
|
-
# and each number within each bucket is a number of calls in the range.
|
|
7
|
-
#
|
|
8
|
-
# (1) 1.00
|
|
9
|
-
# (2) 1.50
|
|
10
|
-
# (3) 2.25
|
|
11
|
-
# (4) 3.38
|
|
12
|
-
# (5) 5.06
|
|
13
|
-
# (6) 7.59
|
|
14
|
-
# (7) 11.39
|
|
15
|
-
# (8) 17.09
|
|
16
|
-
# (9) 25.63
|
|
17
|
-
# (10) 38.44
|
|
18
|
-
# (11) 57.67
|
|
19
|
-
# (12) 86.50
|
|
20
|
-
# (13) 129.75
|
|
21
|
-
# (14) 194.62
|
|
22
|
-
# (15) 291.93
|
|
23
|
-
# (16) 437.89
|
|
24
|
-
# (17) 656.84
|
|
25
|
-
# (18) 985.26
|
|
26
|
-
# (19) 1,477.89
|
|
27
|
-
# (20) 2,216.84
|
|
28
|
-
# (21) 3,325.26
|
|
29
|
-
# (22) 4,987.89
|
|
30
|
-
# (23) 7,481.83
|
|
31
|
-
#
|
|
32
|
-
# Created by fvitale on 2/17/16 based on java implementation by patricioe.
|
|
33
|
-
#
|
|
34
|
-
|
|
35
|
-
class BinarySearchLatencyTracker < NoMethodError
|
|
36
|
-
|
|
37
|
-
BUCKETS = [ 1000, 1500, 2250, 3375, 5063,
|
|
38
|
-
7594, 11391, 17086, 25629, 38443,
|
|
39
|
-
57665, 86498, 129746, 194620, 291929,
|
|
40
|
-
437894, 656841, 985261, 1477892, 2216838,
|
|
41
|
-
3325257, 4987885, 7481828 ].freeze
|
|
42
|
-
|
|
43
|
-
MAX_LATENCY = 7481828
|
|
44
|
-
|
|
45
|
-
attr_accessor :latencies
|
|
46
|
-
|
|
47
|
-
def initialize
|
|
48
|
-
@latencies = Array.new(BUCKETS.length, 0)
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
#
|
|
52
|
-
# Increment the internal counter for the bucket this latency falls into.
|
|
53
|
-
# @param millis
|
|
54
|
-
#
|
|
55
|
-
def add_latency_millis(millis)
|
|
56
|
-
index = find_bucket_index(millis * 1000)
|
|
57
|
-
@latencies[index] += 1
|
|
58
|
-
@latencies
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# Increment the internal counter for the bucket this latency falls into.
|
|
62
|
-
# @param micros
|
|
63
|
-
def add_latency_micros(micros)
|
|
64
|
-
index = find_bucket_index(micros)
|
|
65
|
-
@latencies[index] += 1
|
|
66
|
-
@latencies
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# Returns the list of latencies buckets as an array.
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
# @return the list of latencies buckets as an array.
|
|
73
|
-
def get_latencies
|
|
74
|
-
@latencies
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def get_latency(index)
|
|
78
|
-
return @latencies[index]
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def clear
|
|
82
|
-
@latencies = Array.new(BUCKETS.length, 0)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
#
|
|
86
|
-
# Returns the counts in the bucket this latency falls into.
|
|
87
|
-
# The latencies will not be updated.
|
|
88
|
-
# @param latency
|
|
89
|
-
# @return the bucket content for the latency.
|
|
90
|
-
#
|
|
91
|
-
def get_bucket_for_latency_millis(latency)
|
|
92
|
-
return @latencies[find_bucket_index(latency * 1000)]
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
#
|
|
96
|
-
# Returns the counts in the bucket this latency falls into.
|
|
97
|
-
# The latencies will not be updated.
|
|
98
|
-
# @param latency
|
|
99
|
-
# @return the bucket content for the latency.
|
|
100
|
-
#
|
|
101
|
-
def get_bucket_for_latency_micros(latency)
|
|
102
|
-
return @latencies[find_bucket_index(latency)]
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
private
|
|
106
|
-
|
|
107
|
-
def find_bucket_index(micros)
|
|
108
|
-
if (micros > MAX_LATENCY) then
|
|
109
|
-
return BUCKETS.length - 1
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
if (micros < 1500) then
|
|
113
|
-
return 0
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
index = BUCKETS.find_index(BUCKETS.bsearch {|x| x >= micros })
|
|
117
|
-
|
|
118
|
-
return index
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
end
|
|
122
|
-
end
|