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,3 @@
1
+ require 'digest'
2
+ require 'murmurhash/base'
3
+ require 'murmurhash/murmurhash'
@@ -0,0 +1,90 @@
1
+ require 'forwardable'
2
+
3
+ require 'splitclient-rb/version'
4
+
5
+ require 'splitclient-rb/exceptions/impressions_shutdown_exception'
6
+ require 'splitclient-rb/exceptions/sdk_blocker_timeout_expired_exception'
7
+ require 'splitclient-rb/cache/routers/impression_router'
8
+ require 'splitclient-rb/cache/adapters/memory_adapters/map_adapter'
9
+ require 'splitclient-rb/cache/adapters/memory_adapters/queue_adapter'
10
+ require 'splitclient-rb/cache/adapters/memory_adapter'
11
+ require 'splitclient-rb/cache/adapters/redis_adapter'
12
+ require 'splitclient-rb/cache/repositories/repository'
13
+ require 'splitclient-rb/cache/repositories/segments_repository'
14
+ require 'splitclient-rb/cache/repositories/splits_repository'
15
+ require 'splitclient-rb/cache/repositories/events_repository'
16
+ require 'splitclient-rb/cache/repositories/impressions_repository'
17
+ require 'splitclient-rb/cache/repositories/events/memory_repository'
18
+ require 'splitclient-rb/cache/repositories/events/redis_repository'
19
+ require 'splitclient-rb/cache/repositories/impressions/memory_repository'
20
+ require 'splitclient-rb/cache/repositories/impressions/redis_repository'
21
+ require 'splitclient-rb/cache/repositories/metrics_repository'
22
+ require 'splitclient-rb/cache/repositories/metrics/memory_repository'
23
+ require 'splitclient-rb/cache/repositories/metrics/redis_repository'
24
+ require 'splitclient-rb/cache/senders/impressions_formatter'
25
+ require 'splitclient-rb/cache/senders/impressions_sender'
26
+ require 'splitclient-rb/cache/senders/metrics_sender'
27
+ require 'splitclient-rb/cache/senders/events_sender'
28
+ require 'splitclient-rb/cache/stores/sdk_blocker'
29
+ require 'splitclient-rb/cache/stores/segment_store'
30
+ require 'splitclient-rb/cache/stores/split_store'
31
+
32
+ require 'splitclient-rb/localhost_utils'
33
+ require 'splitclient-rb/clients/localhost_split_client'
34
+ require 'splitclient-rb/clients/split_client'
35
+ require 'splitclient-rb/managers/localhost_split_manager'
36
+ require 'splitclient-rb/managers/split_manager'
37
+ require 'splitclient-rb/split_factory'
38
+ require 'splitclient-rb/split_factory_builder'
39
+ require 'splitclient-rb/localhost_split_factory'
40
+ require 'splitclient-rb/split_config'
41
+
42
+ require 'splitclient-rb/engine/api/faraday_middleware/gzip'
43
+ require 'splitclient-rb/engine/api/client'
44
+ require 'splitclient-rb/engine/api/impressions'
45
+ require 'splitclient-rb/engine/api/metrics'
46
+ require 'splitclient-rb/engine/api/segments'
47
+ require 'splitclient-rb/engine/api/splits'
48
+ require 'splitclient-rb/engine/api/events'
49
+ require 'splitclient-rb/engine/parser/condition'
50
+ require 'splitclient-rb/engine/parser/partition'
51
+ require 'splitclient-rb/engine/parser/split_adapter'
52
+ require 'splitclient-rb/engine/parser/evaluator'
53
+ require 'splitclient-rb/engine/matchers/combiners'
54
+ require 'splitclient-rb/engine/matchers/combining_matcher'
55
+ require 'splitclient-rb/engine/matchers/all_keys_matcher'
56
+ require 'splitclient-rb/engine/matchers/negation_matcher'
57
+ require 'splitclient-rb/engine/matchers/user_defined_segment_matcher'
58
+ require 'splitclient-rb/engine/matchers/whitelist_matcher'
59
+ require 'splitclient-rb/engine/matchers/equal_to_matcher'
60
+ require 'splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher'
61
+ require 'splitclient-rb/engine/matchers/less_than_or_equal_to_matcher'
62
+ require 'splitclient-rb/engine/matchers/between_matcher'
63
+ require 'splitclient-rb/engine/matchers/set_matcher'
64
+ require 'splitclient-rb/engine/matchers/part_of_set_matcher'
65
+ require 'splitclient-rb/engine/matchers/equal_to_set_matcher'
66
+ require 'splitclient-rb/engine/matchers/contains_any_matcher'
67
+ require 'splitclient-rb/engine/matchers/contains_all_matcher'
68
+ require 'splitclient-rb/engine/matchers/starts_with_matcher'
69
+ require 'splitclient-rb/engine/matchers/ends_with_matcher'
70
+ require 'splitclient-rb/engine/matchers/contains_matcher'
71
+ require 'splitclient-rb/engine/matchers/dependency_matcher'
72
+ require 'splitclient-rb/engine/matchers/equal_to_boolean_matcher'
73
+ require 'splitclient-rb/engine/matchers/equal_to_matcher'
74
+ require 'splitclient-rb/engine/matchers/matches_string_matcher'
75
+ require 'splitclient-rb/engine/evaluator/splitter'
76
+ require 'splitclient-rb/engine/metrics/metrics'
77
+ require 'splitclient-rb/engine/metrics/binary_search_latency_tracker'
78
+ require 'splitclient-rb/engine/models/split'
79
+ require 'splitclient-rb/engine/models/label'
80
+ require 'splitclient-rb/engine/models/treatment'
81
+ require 'splitclient-rb/utilitites'
82
+
83
+ # C extension
84
+ require 'murmurhash/murmurhash_mri'
85
+
86
+ module SplitIoClient
87
+ def self.root
88
+ File.dirname(__dir__)
89
+ end
90
+ end
@@ -0,0 +1,12 @@
1
+ require 'concurrent'
2
+
3
+ module SplitIoClient
4
+ module Cache
5
+ module Adapters
6
+ # Memory adapter can have different implementations, this class is used as a delegator to
7
+ # this implementations
8
+ class MemoryAdapter < SimpleDelegator
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,133 @@
1
+ require 'concurrent'
2
+
3
+ module SplitIoClient
4
+ module Cache
5
+ module Adapters
6
+ module MemoryAdapters
7
+ # Memory adapter implementation, which stores everything inside thread-safe Map
8
+ class MapAdapter
9
+ def initialize
10
+ @map = Concurrent::Map.new
11
+ end
12
+
13
+ def clear(_ = nil)
14
+ initialize
15
+ end
16
+
17
+ # Map
18
+ def initialize_map(key)
19
+ @map[key] = Concurrent::Map.new
20
+ end
21
+
22
+ def add_to_map(key, field, value)
23
+ initialize_map(key) unless @map[key]
24
+
25
+ @map[key].put(field, value)
26
+ end
27
+
28
+ def find_in_map(key, field)
29
+ return nil if @map[key].nil?
30
+
31
+ @map[key].get(field)
32
+ end
33
+
34
+ def delete_from_map(key, fields)
35
+ if fields.is_a? Array
36
+ fields.each { |field| @map[key].delete(field) }
37
+ else
38
+ @map[key].delete(fields)
39
+ end
40
+ end
41
+
42
+ def in_map?(key, field)
43
+ return false if @map[key].nil?
44
+
45
+ @map[key].key?(field)
46
+ end
47
+
48
+ def map_keys(key)
49
+ @map[key].keys
50
+ end
51
+
52
+ def get_map(key)
53
+ @map[key]
54
+ end
55
+
56
+ # String
57
+ def string(key)
58
+ @map[key]
59
+ end
60
+
61
+ def set_string(key, str)
62
+ @map[key] = str
63
+ end
64
+
65
+ def find_strings_by_prefix(prefix)
66
+ @map.keys.select { |str| str.start_with? prefix }
67
+ end
68
+
69
+ def multiple_strings(keys)
70
+ keys.each_with_object({}) do |key, memo|
71
+ memo[key] = string(key)
72
+ end
73
+ end
74
+
75
+ # Bool
76
+ def set_bool(key, val)
77
+ @map[key] = val
78
+ end
79
+
80
+ def bool(key)
81
+ @map[key]
82
+ end
83
+
84
+ # Set
85
+ alias_method :initialize_set, :initialize_map
86
+ alias_method :get_set, :map_keys
87
+ alias_method :delete_from_set, :delete_from_map
88
+ alias_method :in_set?, :in_map?
89
+ alias_method :find_sets_by_prefix, :find_strings_by_prefix
90
+
91
+ def add_to_set(key, values)
92
+ if values.is_a? Array
93
+ values.each { |value| add_to_map(key, value, 1) }
94
+ else
95
+ add_to_map(key, values, 1)
96
+ end
97
+ end
98
+
99
+ def get_all_from_set(key)
100
+ @map[key].keys
101
+ end
102
+
103
+ def union_sets(set_keys)
104
+ array = set_keys.each_with_object([]) do |key, memo|
105
+ memo << get_set(key)
106
+ end.flatten
107
+
108
+ Set.new(array)
109
+ end
110
+
111
+ # General
112
+ def exists?(key)
113
+ !@map[key].nil?
114
+ end
115
+
116
+ def delete(key)
117
+ if key.is_a? Array
118
+ key.each { |k| @map.delete(k) }
119
+ else
120
+ @map.delete(key)
121
+ end
122
+ end
123
+
124
+ # This method is used in Redis adapter
125
+ # "stubbing" it here to keep the interface
126
+ def pipelined(&block)
127
+ block.call
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,44 @@
1
+ module SplitIoClient
2
+ module Cache
3
+ module Adapters
4
+ module MemoryAdapters
5
+ # Memory adapter implementation, which stores everything inside queue
6
+ class QueueAdapter
7
+ def initialize(max_size)
8
+ @max_size = max_size
9
+ @queue = Queue.new
10
+ @current_size = Concurrent::AtomicFixnum.new(0)
11
+ end
12
+
13
+ def clear(_ = nil)
14
+ @queue = Queue.new
15
+ @current_size.value = 0
16
+ end
17
+
18
+ # Adds data to queue in non-blocking mode
19
+ def add_to_queue(data)
20
+ fail ThreadError if @current_size.value >= @max_size
21
+
22
+ @queue.push(data)
23
+
24
+ @current_size.increment
25
+ end
26
+
27
+ # Get all items from the queue
28
+ def clear
29
+ items = []
30
+
31
+ loop do
32
+ items << @queue.pop(true)
33
+
34
+ @current_size.decrement
35
+ end
36
+
37
+ rescue ThreadError
38
+ items
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,165 @@
1
+ require 'json'
2
+
3
+ module SplitIoClient
4
+ module Cache
5
+ module Adapters
6
+ # Redis adapter used to provide interface to Redis
7
+ class RedisAdapter
8
+ SCAN_SLICE = 5000
9
+
10
+ attr_reader :redis
11
+
12
+ def initialize(redis_url)
13
+ connection = redis_url.is_a?(Hash) ? redis_url : { url: redis_url }
14
+
15
+ @redis = Redis.new(connection)
16
+ end
17
+
18
+ # Map
19
+ def initialize_map(key)
20
+ # No need to initialize hash/map in Redis
21
+ end
22
+
23
+ def add_to_map(key, field, value)
24
+ @redis.hset(key, field, value)
25
+ end
26
+
27
+ def find_in_map(key, field)
28
+ @redis.hget(key, field)
29
+ end
30
+
31
+ def delete_from_map(key, field)
32
+ @redis.hdel(key, field)
33
+ end
34
+
35
+ def in_map?(key, field)
36
+ @redis.hexists(key, field)
37
+ end
38
+
39
+ def map_keys(key)
40
+ @redis.hkeys(key)
41
+ end
42
+
43
+ def get_map(key)
44
+ @redis.hgetall(key)
45
+ end
46
+
47
+ # String
48
+ def string(key)
49
+ @redis.get(key)
50
+ end
51
+
52
+ def set_string(key, str)
53
+ @redis.set(key, str)
54
+ end
55
+
56
+ def find_strings_by_prefix(prefix)
57
+ memo = { items: [], cursor: 0 }
58
+
59
+ loop do
60
+ memo[:cursor], items = @redis.scan(memo[:cursor], match: "#{prefix}*", count: SCAN_SLICE)
61
+
62
+ memo[:items].push(*items)
63
+
64
+ break if memo[:cursor] == '0'
65
+ end
66
+
67
+ memo[:items]
68
+ end
69
+
70
+ def multiple_strings(keys)
71
+ Hash[keys.zip(@redis.mget(keys))]
72
+ end
73
+
74
+ def append_to_string(key, val)
75
+ @redis.append(key, val)
76
+ end
77
+
78
+ # Bool
79
+ def set_bool(key, val)
80
+ @redis.set(key, val.to_s)
81
+ end
82
+
83
+ def bool(key)
84
+ @redis.get(key) == 'true'
85
+ end
86
+
87
+ # Set
88
+ alias_method :initialize_set, :initialize_map
89
+ alias_method :find_sets_by_prefix, :find_strings_by_prefix
90
+
91
+ def add_to_set(key, val)
92
+ @redis.sadd(key, val)
93
+ end
94
+
95
+ def delete_from_set(key, val)
96
+ @redis.srem(key, val)
97
+ end
98
+
99
+ def get_set(key)
100
+ @redis.smembers(key)
101
+ end
102
+
103
+ def in_set?(key, val)
104
+ @redis.sismember(key, val)
105
+ end
106
+
107
+ def get_all_from_set(key)
108
+ @redis.smembers(key)
109
+ end
110
+
111
+ def union_sets(set_keys)
112
+ return [] if set_keys == []
113
+
114
+ @redis.sunion(set_keys)
115
+ end
116
+
117
+ def random_set_elements(key, count)
118
+ @redis.srandmember(key, count)
119
+ end
120
+
121
+ # Queue
122
+ def add_to_queue(key, val)
123
+ @redis.rpush(key, val)
124
+ end
125
+
126
+ def get_from_queue(key, count)
127
+ items = @redis.lrange(key, 0, count - 1)
128
+ fetched_count = items.size
129
+ items_to_remove = (fetched_count == count) ? count : fetched_count
130
+
131
+ @redis.ltrim(key, items_to_remove, -1)
132
+
133
+ items
134
+ end
135
+
136
+ # General
137
+ def exists?(key)
138
+ @redis.exists(key)
139
+ end
140
+
141
+ def delete(key)
142
+ return nil if key == []
143
+
144
+ @redis.del(key)
145
+ end
146
+
147
+ def inc(key, inc = 1)
148
+ @redis.incrby(key, inc)
149
+ end
150
+
151
+ def pipelined(&block)
152
+ @redis.pipelined do
153
+ block.call
154
+ end
155
+ end
156
+
157
+ def clear(prefix)
158
+ keys = @redis.keys("#{prefix}*")
159
+
160
+ keys.map { |key| @redis.del(key) }
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end