splitclient-rb 4.5.1-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.
Files changed (96) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +45 -0
  3. data/CHANGES.txt +147 -0
  4. data/Detailed-README.md +571 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +13 -0
  7. data/NEWS +75 -0
  8. data/README.md +43 -0
  9. data/Rakefile +24 -0
  10. data/exe/splitio +96 -0
  11. data/ext/murmurhash/MurmurHash3.java +162 -0
  12. data/lib/murmurhash/base.rb +58 -0
  13. data/lib/murmurhash/murmurhash.jar +0 -0
  14. data/lib/murmurhash/murmurhash_mri.rb +3 -0
  15. data/lib/splitclient-rb.rb +90 -0
  16. data/lib/splitclient-rb/cache/adapters/memory_adapter.rb +12 -0
  17. data/lib/splitclient-rb/cache/adapters/memory_adapters/map_adapter.rb +133 -0
  18. data/lib/splitclient-rb/cache/adapters/memory_adapters/queue_adapter.rb +44 -0
  19. data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +165 -0
  20. data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +30 -0
  21. data/lib/splitclient-rb/cache/repositories/events/redis_repository.rb +29 -0
  22. data/lib/splitclient-rb/cache/repositories/events_repository.rb +41 -0
  23. data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +49 -0
  24. data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +78 -0
  25. data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +21 -0
  26. data/lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb +129 -0
  27. data/lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb +98 -0
  28. data/lib/splitclient-rb/cache/repositories/metrics_repository.rb +22 -0
  29. data/lib/splitclient-rb/cache/repositories/repository.rb +23 -0
  30. data/lib/splitclient-rb/cache/repositories/segments_repository.rb +82 -0
  31. data/lib/splitclient-rb/cache/repositories/splits_repository.rb +106 -0
  32. data/lib/splitclient-rb/cache/routers/impression_router.rb +52 -0
  33. data/lib/splitclient-rb/cache/senders/events_sender.rb +47 -0
  34. data/lib/splitclient-rb/cache/senders/impressions_formatter.rb +73 -0
  35. data/lib/splitclient-rb/cache/senders/impressions_sender.rb +67 -0
  36. data/lib/splitclient-rb/cache/senders/metrics_sender.rb +49 -0
  37. data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +48 -0
  38. data/lib/splitclient-rb/cache/stores/segment_store.rb +82 -0
  39. data/lib/splitclient-rb/cache/stores/split_store.rb +97 -0
  40. data/lib/splitclient-rb/clients/localhost_split_client.rb +92 -0
  41. data/lib/splitclient-rb/clients/split_client.rb +214 -0
  42. data/lib/splitclient-rb/engine/api/client.rb +74 -0
  43. data/lib/splitclient-rb/engine/api/events.rb +48 -0
  44. data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +55 -0
  45. data/lib/splitclient-rb/engine/api/impressions.rb +42 -0
  46. data/lib/splitclient-rb/engine/api/metrics.rb +61 -0
  47. data/lib/splitclient-rb/engine/api/segments.rb +62 -0
  48. data/lib/splitclient-rb/engine/api/splits.rb +60 -0
  49. data/lib/splitclient-rb/engine/evaluator/splitter.rb +123 -0
  50. data/lib/splitclient-rb/engine/matchers/all_keys_matcher.rb +46 -0
  51. data/lib/splitclient-rb/engine/matchers/between_matcher.rb +56 -0
  52. data/lib/splitclient-rb/engine/matchers/combiners.rb +9 -0
  53. data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +86 -0
  54. data/lib/splitclient-rb/engine/matchers/contains_all_matcher.rb +21 -0
  55. data/lib/splitclient-rb/engine/matchers/contains_any_matcher.rb +19 -0
  56. data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +30 -0
  57. data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +20 -0
  58. data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +26 -0
  59. data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +27 -0
  60. data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +54 -0
  61. data/lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb +19 -0
  62. data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +53 -0
  63. data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +53 -0
  64. data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +24 -0
  65. data/lib/splitclient-rb/engine/matchers/negation_matcher.rb +60 -0
  66. data/lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb +23 -0
  67. data/lib/splitclient-rb/engine/matchers/set_matcher.rb +20 -0
  68. data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +26 -0
  69. data/lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb +45 -0
  70. data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +66 -0
  71. data/lib/splitclient-rb/engine/metrics/binary_search_latency_tracker.rb +128 -0
  72. data/lib/splitclient-rb/engine/metrics/metrics.rb +83 -0
  73. data/lib/splitclient-rb/engine/models/label.rb +8 -0
  74. data/lib/splitclient-rb/engine/models/split.rb +17 -0
  75. data/lib/splitclient-rb/engine/models/treatment.rb +3 -0
  76. data/lib/splitclient-rb/engine/parser/condition.rb +210 -0
  77. data/lib/splitclient-rb/engine/parser/evaluator.rb +118 -0
  78. data/lib/splitclient-rb/engine/parser/partition.rb +35 -0
  79. data/lib/splitclient-rb/engine/parser/split_adapter.rb +88 -0
  80. data/lib/splitclient-rb/exceptions/impressions_shutdown_exception.rb +4 -0
  81. data/lib/splitclient-rb/exceptions/sdk_blocker_timeout_expired_exception.rb +4 -0
  82. data/lib/splitclient-rb/localhost_split_factory.rb +13 -0
  83. data/lib/splitclient-rb/localhost_utils.rb +36 -0
  84. data/lib/splitclient-rb/managers/localhost_split_manager.rb +45 -0
  85. data/lib/splitclient-rb/managers/split_manager.rb +77 -0
  86. data/lib/splitclient-rb/split_config.rb +391 -0
  87. data/lib/splitclient-rb/split_factory.rb +35 -0
  88. data/lib/splitclient-rb/split_factory_builder.rb +16 -0
  89. data/lib/splitclient-rb/utilitites.rb +41 -0
  90. data/lib/splitclient-rb/version.rb +3 -0
  91. data/splitclient-rb.gemspec +50 -0
  92. data/splitio.yml.example +7 -0
  93. data/tasks/benchmark_get_treatment.rake +43 -0
  94. data/tasks/irb.rake +4 -0
  95. data/tasks/rspec.rake +3 -0
  96. metadata +321 -0
@@ -0,0 +1,46 @@
1
+ module SplitIoClient
2
+ #
3
+ # class to implement the all keys matcher
4
+ #
5
+ class AllKeysMatcher
6
+ MATCHER_TYPE = 'ALL_KEYS'.freeze
7
+
8
+ #
9
+ # evaluates if the key matches the matcher
10
+ #
11
+ # @return [boolean] true for all instances
12
+ def match?(_args)
13
+ true
14
+ end
15
+
16
+ #
17
+ # evaluates if the given object equals the matcher
18
+ #
19
+ # @param obj [object] object to be evaluated
20
+ #
21
+ # @return [boolean] true if obj equals the matcher
22
+ def equals?(obj)
23
+ if obj.nil?
24
+ false
25
+ elsif equal?(obj)
26
+ true
27
+ elsif !obj.instance_of?(AllKeysMatcher)
28
+ false
29
+ else
30
+ true
31
+ end
32
+ end
33
+
34
+ def string_type?
35
+ false
36
+ end
37
+
38
+ #
39
+ # function to print string value for this matcher
40
+ #
41
+ # @reutrn [string] string value of this matcher
42
+ def to_s
43
+ 'in segment all'
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,56 @@
1
+ module SplitIoClient
2
+ class BetweenMatcher
3
+ MATCHER_TYPE = 'BETWEEN'.freeze
4
+
5
+ attr_reader :attribute
6
+
7
+ def initialize(attribute_hash)
8
+ @attribute = attribute_hash[:attribute]
9
+ @data_type = attribute_hash[:data_type]
10
+ @start_value = formatted_value(attribute_hash[:start_value], true)
11
+ @end_value = formatted_value(attribute_hash[:end_value], true)
12
+ end
13
+
14
+ def match?(args)
15
+ return false if !args.key?(:attributes) && !args.key?(:value)
16
+ return false if args.key?(:value) && args[:value].nil?
17
+ return false if args.key?(:attributes) && args[:attributes].nil?
18
+
19
+ value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
20
+ return false unless value.is_a?(Integer)
21
+
22
+ (@start_value..@end_value).include? value
23
+ end
24
+
25
+ def equals?(obj)
26
+ if obj.nil?
27
+ false
28
+ elsif !obj.instance_of?(BetweenMatcher)
29
+ false
30
+ elsif self.equal?(obj)
31
+ true
32
+ else
33
+ false
34
+ end
35
+ end
36
+
37
+ def string_type?
38
+ false
39
+ end
40
+
41
+ private
42
+
43
+ def formatted_value(value, sdk_data = false)
44
+ case @data_type
45
+ when 'NUMBER'
46
+ value
47
+ when 'DATETIME'
48
+ value = value / 1000 if sdk_data
49
+
50
+ SplitIoClient::Utilities.to_milis_zero_out_from_seconds(value)
51
+ else
52
+ @logger.error('Invalid data type')
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,9 @@
1
+ module SplitIoClient
2
+ #
3
+ # class to represent combiner values
4
+ #
5
+ class Combiners
6
+ # available combiners of the sdk
7
+ AND = 'AND'.freeze
8
+ end
9
+ end
@@ -0,0 +1,86 @@
1
+ module SplitIoClient
2
+ #
3
+ # class to implement the combining matcher
4
+ #
5
+ class CombiningMatcher
6
+ MATCHER_TYPE = 'COMBINING_MATCHER'.freeze
7
+
8
+ def initialize(combiner = '', matchers = [])
9
+ @combiner = combiner
10
+ @matchers = matchers
11
+ end
12
+
13
+ #
14
+ # evaluates if the key matches the matchers within the combiner
15
+ #
16
+ # @param matching_key [string] key value to be matched
17
+ # @param bucketing_key [string] bucketing key to be matched
18
+ # @param evaluator [instance of Evaluator class]
19
+ # @param attributes [hash]
20
+ #
21
+ # @return [boolean]
22
+ def match?(args)
23
+ return false if @matchers.empty?
24
+
25
+ case @combiner
26
+ when Combiners::AND
27
+ return eval_and(args)
28
+ else
29
+ @logger.error('Invalid combiner type')
30
+ end
31
+
32
+ false
33
+ end
34
+
35
+ #
36
+ # auxiliary method to evaluate each of the matchers within the combiner
37
+ #
38
+ # @param matching_key [string] key value to be matched
39
+ # @param bucketing_key [string] bucketing key to be matched
40
+ # @param evaluator [Evaluator] used in dependency_matcher
41
+ # @param attributes [hash] attributes to pass to the treatment class
42
+ #
43
+ # @return [boolean] match value for combiner delegates
44
+ def eval_and(args)
45
+ # Convert all keys to symbols
46
+ args[:attributes] = args[:attributes].inject({}){ |memo, (k,v)| memo[k.to_sym] = v; memo } if args && args[:attributes]
47
+ @matchers.all? do |matcher|
48
+ if match_with_key?(matcher)
49
+ matcher.match?(value: args[:matching_key])
50
+ else
51
+ matcher.match?(args)
52
+ end
53
+ end
54
+ end
55
+
56
+ def match_with_key?(matcher)
57
+ matcher.respond_to?(:attribute) && matcher.attribute.nil? && matcher.string_type?
58
+ end
59
+
60
+ #
61
+ # evaluates if the given object equals the matcher
62
+ #
63
+ # @param obj [object] object to be evaluated
64
+ #
65
+ # @returns [boolean] true if obj equals the matcher
66
+ def equals?(obj)
67
+ if obj.nil?
68
+ false
69
+ elsif !obj.instance_of?(CombiningMatcher)
70
+ false
71
+ elsif self.equal?(obj)
72
+ true
73
+ else
74
+ false
75
+ end
76
+ end
77
+
78
+ #
79
+ # function to print string value for this matcher
80
+ #
81
+ # @reutrn [string] string value of this matcher
82
+ def to_s
83
+ @matcher_list.map(&:to_s).join("#{@combiner} ")
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,21 @@
1
+ module SplitIoClient
2
+ class ContainsAllMatcher < SetMatcher
3
+ MATCHER_TYPE = 'CONTAINS_ALL'.freeze
4
+
5
+ attr_reader :attribute
6
+
7
+ def initialize(attribute, remote_array)
8
+ super(attribute, remote_array)
9
+ end
10
+
11
+ def match?(args)
12
+ return false if @remote_set.empty?
13
+
14
+ @remote_set.subset? local_set(args[:attributes], @attribute)
15
+ end
16
+
17
+ def string_type?
18
+ false
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module SplitIoClient
2
+ class ContainsAnyMatcher < SetMatcher
3
+ MATCHER_TYPE = 'CONTAINS_ANY'.freeze
4
+
5
+ attr_reader :attribute
6
+
7
+ def initialize(attribute, remote_array)
8
+ super(attribute, remote_array)
9
+ end
10
+
11
+ def match?(args)
12
+ local_set(args[:attributes], @attribute).intersect? @remote_set
13
+ end
14
+
15
+ def string_type?
16
+ false
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ module SplitIoClient
2
+ class ContainsMatcher
3
+ MATCHER_TYPE = 'CONTAINS_WITH'.freeze
4
+
5
+ attr_reader :attribute
6
+
7
+ def initialize(attribute, substr_list)
8
+ @attribute = attribute
9
+ @substr_list = substr_list
10
+ end
11
+
12
+ def match?(args)
13
+ return false if !args.key?(:attributes) && !args.key?(:value)
14
+ return false if args.key?(:value) && args[:value].nil?
15
+ return false if args.key?(:attributes) && args[:attributes].nil?
16
+
17
+ value = args[:value] || args[:attributes].fetch(@attribute) do |a|
18
+ args[:attributes][a.to_s] || args[:attributes][a.to_sym]
19
+ end
20
+
21
+ return false if @substr_list.empty?
22
+
23
+ @substr_list.any? { |substr| value.to_s.include? substr }
24
+ end
25
+
26
+ def string_type?
27
+ true
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,20 @@
1
+ module SplitIoClient
2
+ class DependencyMatcher
3
+ MATCHER_TYPE = 'IN_SPLIT_TREATMENT'.freeze
4
+
5
+ def initialize(split, treatments)
6
+ @split = split
7
+ @treatments = treatments
8
+ end
9
+
10
+ def match?(args)
11
+ keys = { matching_key: args[:matching_key], bucketing_key: args[:bucketing_key] }
12
+
13
+ @treatments.include?(args[:evaluator].call(keys, @split, args[:attributes])[:treatment])
14
+ end
15
+
16
+ def string_type?
17
+ false
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,26 @@
1
+ module SplitIoClient
2
+ class EndsWithMatcher
3
+ MATCHER_TYPE = 'ENDS_WITH'.freeze
4
+
5
+ attr_reader :attribute
6
+
7
+ def initialize(attribute, suffix_list)
8
+ @attribute = attribute
9
+ @suffix_list = suffix_list
10
+ end
11
+
12
+ def match?(args)
13
+ value = args[:value] || args[:attributes].fetch(@attribute) do |a|
14
+ args[:attributes][a.to_s] || args[:attributes][a.to_sym]
15
+ end
16
+
17
+ return false if @suffix_list.empty?
18
+
19
+ @suffix_list.any? { |suffix| value.to_s.end_with? suffix }
20
+ end
21
+
22
+ def string_type?
23
+ true
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ module SplitIoClient
2
+ class EqualToBooleanMatcher
3
+ MATCHER_TYPE = 'EQUAL_TO_BOOLEAN'.freeze
4
+
5
+ attr_reader :attribute
6
+
7
+ def initialize(attribute, boolean)
8
+ @attribute = attribute
9
+ @boolean = boolean
10
+ end
11
+
12
+ def match?(args)
13
+ value = args[:attributes].fetch(@attribute) do |a|
14
+ args[:attributes][a.to_s] || args[:attributes][a.to_sym]
15
+ end
16
+
17
+ value = false if value.to_s.downcase == 'false'
18
+ value = true if value.to_s.downcase == 'true'
19
+
20
+ value == @boolean
21
+ end
22
+
23
+ def string_type?
24
+ false
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,54 @@
1
+ module SplitIoClient
2
+ class EqualToMatcher
3
+ MATCHER_TYPE = 'EQUAL_TO'.freeze
4
+
5
+ attr_reader :attribute
6
+
7
+ def initialize(attribute_hash)
8
+ @attribute = attribute_hash[:attribute]
9
+ @data_type = attribute_hash[:data_type]
10
+ @value = formatted_value(attribute_hash[:value], true)
11
+ end
12
+
13
+ def match?(args)
14
+ return false if !args.key?(:attributes) && !args.key?(:value)
15
+ return false if args.key?(:value) && args[:value].nil?
16
+ return false if args.key?(:attributes) && args[:attributes].nil?
17
+
18
+ value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
19
+
20
+ value.is_a?(Integer) ? (value == @value) : false
21
+ end
22
+
23
+ def equals?(obj)
24
+ if obj.nil?
25
+ false
26
+ elsif !obj.instance_of?(EqualToMatcher)
27
+ false
28
+ elsif self.equal?(obj)
29
+ true
30
+ else
31
+ false
32
+ end
33
+ end
34
+
35
+ def string_type?
36
+ false
37
+ end
38
+
39
+ private
40
+
41
+ def formatted_value(value, sdk_data = false)
42
+ case @data_type
43
+ when 'NUMBER'
44
+ value
45
+ when 'DATETIME'
46
+ value = value / 1000 if sdk_data
47
+
48
+ SplitIoClient::Utilities.to_milis_zero_out_from_hour value
49
+ else
50
+ @logger.error('Invalid data type')
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,19 @@
1
+ module SplitIoClient
2
+ class EqualToSetMatcher < SetMatcher
3
+ MATCHER_TYPE = 'EQUAL_TO_SET'.freeze
4
+
5
+ attr_reader :attribute
6
+
7
+ def initialize(attribute, remote_array)
8
+ super(attribute, remote_array)
9
+ end
10
+
11
+ def match?(args)
12
+ local_set(args[:attributes], @attribute) == @remote_set
13
+ end
14
+
15
+ def string_type?
16
+ false
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,53 @@
1
+ module SplitIoClient
2
+ class GreaterThanOrEqualToMatcher
3
+ MATCHER_TYPE = 'GREATER_THAN_OR_EQUAL_TO'.freeze
4
+
5
+ attr_reader :attribute
6
+
7
+ def initialize(attribute_hash)
8
+ @attribute = attribute_hash[:attribute]
9
+ @data_type = attribute_hash[:data_type]
10
+ @value = formatted_value(attribute_hash[:value], true)
11
+ end
12
+
13
+ def match?(args)
14
+ return false if !args.key?(:attributes) && !args.key?(:value)
15
+ return false if args.key?(:value) && args[:value].nil?
16
+ return false if args.key?(:attributes) && args[:attributes].nil?
17
+
18
+ value = formatted_value(args[:value] || args[:attributes][@attribute.to_sym])
19
+
20
+ value.is_a?(Integer) ? (value >= @value) : false
21
+ end
22
+
23
+ def equals?(obj)
24
+ if obj.nil?
25
+ false
26
+ elsif !obj.instance_of?(GreaterThanOrEqualToMatcher)
27
+ false
28
+ elsif self.equal?(obj)
29
+ true
30
+ else
31
+ false
32
+ end
33
+ end
34
+
35
+ def string_type?
36
+ false
37
+ end
38
+
39
+ private
40
+
41
+ def formatted_value(value, sdk_data = false)
42
+ case @data_type
43
+ when 'NUMBER'
44
+ return value
45
+ when 'DATETIME'
46
+ value = value / 1000 if sdk_data # sdk returns already miliseconds, turning to seconds to do a correct zero_our
47
+ return SplitIoClient::Utilities.to_milis_zero_out_from_seconds(value)
48
+ else
49
+ @logger.error('Invalid data type')
50
+ end
51
+ end
52
+ end
53
+ end