splitclient-rb 4.5.1-java

Sign up to get free protection for your applications and to get access to all the features.
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