splitclient-rb 6.3.0 → 8.11.0

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 (192) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -0
  3. data/.github/pull_request_template.md +9 -0
  4. data/.github/workflows/ci.yml +90 -0
  5. data/.github/workflows/update-license-year.yml +45 -0
  6. data/.gitignore +4 -0
  7. data/.rubocop.yml +46 -3
  8. data/CHANGES.txt +158 -11
  9. data/CONTRIBUTORS-GUIDE.md +49 -0
  10. data/LICENSE +169 -13
  11. data/NOTICE.txt +5 -0
  12. data/README.md +67 -27
  13. data/Rakefile +1 -8
  14. data/ext/murmurhash/3_x64_128.c +117 -0
  15. data/ext/murmurhash/murmurhash.c +5 -1
  16. data/lib/murmurhash/murmurhash.jar +0 -0
  17. data/lib/splitclient-rb/cache/adapters/cache_adapter.rb +3 -3
  18. data/lib/splitclient-rb/cache/adapters/memory_adapters/map_adapter.rb +4 -0
  19. data/lib/splitclient-rb/cache/adapters/memory_adapters/queue_adapter.rb +7 -0
  20. data/lib/splitclient-rb/cache/adapters/redis_adapter.rb +12 -4
  21. data/lib/splitclient-rb/cache/fetchers/segment_fetcher.rb +83 -0
  22. data/lib/splitclient-rb/cache/fetchers/split_fetcher.rb +70 -0
  23. data/lib/splitclient-rb/cache/filter/bloom_filter.rb +67 -0
  24. data/lib/splitclient-rb/cache/filter/filter_adapter.rb +32 -0
  25. data/lib/splitclient-rb/cache/filter/flag_set_filter.rb +40 -0
  26. data/lib/splitclient-rb/cache/hashers/impression_hasher.rb +34 -0
  27. data/lib/splitclient-rb/cache/observers/impression_observer.rb +22 -0
  28. data/lib/splitclient-rb/cache/observers/noop_impression_observer.rb +10 -0
  29. data/lib/splitclient-rb/cache/repositories/events/memory_repository.rb +26 -14
  30. data/lib/splitclient-rb/cache/repositories/events/redis_repository.rb +9 -14
  31. data/lib/splitclient-rb/cache/repositories/events_repository.rb +31 -10
  32. data/lib/splitclient-rb/cache/repositories/flag_sets/memory_repository.rb +40 -0
  33. data/lib/splitclient-rb/cache/repositories/flag_sets/redis_repository.rb +49 -0
  34. data/lib/splitclient-rb/cache/repositories/impressions/memory_repository.rb +22 -23
  35. data/lib/splitclient-rb/cache/repositories/impressions/redis_repository.rb +15 -22
  36. data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +6 -31
  37. data/lib/splitclient-rb/cache/repositories/repository.rb +6 -5
  38. data/lib/splitclient-rb/cache/repositories/rule_based_segments_repository.rb +136 -0
  39. data/lib/splitclient-rb/cache/repositories/segments_repository.rb +46 -6
  40. data/lib/splitclient-rb/cache/repositories/splits_repository.rb +232 -43
  41. data/lib/splitclient-rb/cache/routers/impression_router.rb +24 -22
  42. data/lib/splitclient-rb/cache/senders/events_sender.rb +12 -29
  43. data/lib/splitclient-rb/cache/senders/impressions_adapter/memory_sender.rb +71 -0
  44. data/lib/splitclient-rb/cache/senders/impressions_adapter/redis_sender.rb +69 -0
  45. data/lib/splitclient-rb/cache/senders/impressions_count_sender.rb +43 -0
  46. data/lib/splitclient-rb/cache/senders/impressions_formatter.rb +27 -13
  47. data/lib/splitclient-rb/cache/senders/impressions_sender.rb +11 -25
  48. data/lib/splitclient-rb/cache/senders/impressions_sender_adapter.rb +21 -0
  49. data/lib/splitclient-rb/cache/senders/localhost_repo_cleaner.rb +47 -0
  50. data/lib/splitclient-rb/cache/stores/localhost_split_builder.rb +95 -0
  51. data/lib/splitclient-rb/cache/stores/localhost_split_store.rb +110 -0
  52. data/lib/splitclient-rb/cache/stores/store_utils.rb +13 -0
  53. data/lib/splitclient-rb/clients/split_client.rb +385 -138
  54. data/lib/splitclient-rb/constants.rb +16 -0
  55. data/lib/splitclient-rb/engine/api/client.rb +38 -43
  56. data/lib/splitclient-rb/engine/api/events.rb +19 -11
  57. data/lib/splitclient-rb/engine/api/faraday_middleware/gzip.rb +1 -0
  58. data/lib/splitclient-rb/engine/api/impressions.rb +49 -14
  59. data/lib/splitclient-rb/engine/api/segments.rb +31 -24
  60. data/lib/splitclient-rb/engine/api/splits.rb +108 -33
  61. data/lib/splitclient-rb/engine/api/telemetry_api.rb +47 -0
  62. data/lib/splitclient-rb/engine/auth_api_client.rb +96 -0
  63. data/lib/splitclient-rb/engine/back_off.rb +26 -0
  64. data/lib/splitclient-rb/engine/common/impressions_counter.rb +45 -0
  65. data/lib/splitclient-rb/engine/common/impressions_manager.rb +165 -0
  66. data/lib/splitclient-rb/engine/common/noop_impressions_counter.rb +27 -0
  67. data/lib/splitclient-rb/engine/events/events_delivery.rb +20 -0
  68. data/lib/splitclient-rb/engine/events/events_manager.rb +194 -0
  69. data/lib/splitclient-rb/engine/events/events_manager_config.rb +96 -0
  70. data/lib/splitclient-rb/engine/events/events_task.rb +50 -0
  71. data/lib/splitclient-rb/engine/events/noop_events_queue.rb +13 -0
  72. data/lib/splitclient-rb/engine/fallback_treatment_calculator.rb +48 -0
  73. data/lib/splitclient-rb/engine/impressions/noop_unique_keys_tracker.rb +17 -0
  74. data/lib/splitclient-rb/engine/impressions/unique_keys_tracker.rb +144 -0
  75. data/lib/splitclient-rb/engine/matchers/all_keys_matcher.rb +1 -1
  76. data/lib/splitclient-rb/engine/matchers/between_matcher.rb +7 -5
  77. data/lib/splitclient-rb/engine/matchers/between_semver_matcher.rb +33 -0
  78. data/lib/splitclient-rb/engine/matchers/combining_matcher.rb +10 -8
  79. data/lib/splitclient-rb/engine/matchers/contains_all_matcher.rb +2 -6
  80. data/lib/splitclient-rb/engine/matchers/contains_any_matcher.rb +1 -5
  81. data/lib/splitclient-rb/engine/matchers/contains_matcher.rb +7 -5
  82. data/lib/splitclient-rb/engine/matchers/dependency_matcher.rb +6 -5
  83. data/lib/splitclient-rb/engine/matchers/ends_with_matcher.rb +5 -4
  84. data/lib/splitclient-rb/engine/matchers/equal_to_boolean_matcher.rb +3 -2
  85. data/lib/splitclient-rb/engine/matchers/equal_to_matcher.rb +6 -4
  86. data/lib/splitclient-rb/engine/matchers/equal_to_semver_matcher.rb +28 -0
  87. data/lib/splitclient-rb/engine/matchers/equal_to_set_matcher.rb +1 -5
  88. data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_matcher.rb +6 -4
  89. data/lib/splitclient-rb/engine/matchers/greater_than_or_equal_to_semver_matcher.rb +28 -0
  90. data/lib/splitclient-rb/engine/matchers/in_list_semver_matcher.rb +36 -0
  91. data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_matcher.rb +6 -4
  92. data/lib/splitclient-rb/engine/matchers/less_than_or_equal_to_semver_matcher.rb +28 -0
  93. data/lib/splitclient-rb/engine/matchers/matcher.rb +22 -0
  94. data/lib/splitclient-rb/engine/matchers/matches_string_matcher.rb +3 -2
  95. data/lib/splitclient-rb/engine/matchers/negation_matcher.rb +3 -2
  96. data/lib/splitclient-rb/engine/matchers/part_of_set_matcher.rb +2 -6
  97. data/lib/splitclient-rb/engine/matchers/prerequisites_matcher.rb +31 -0
  98. data/lib/splitclient-rb/engine/matchers/rule_based_segment_matcher.rb +78 -0
  99. data/lib/splitclient-rb/engine/matchers/semver.rb +201 -0
  100. data/lib/splitclient-rb/engine/matchers/set_matcher.rb +2 -1
  101. data/lib/splitclient-rb/engine/matchers/starts_with_matcher.rb +4 -3
  102. data/lib/splitclient-rb/engine/matchers/user_defined_segment_matcher.rb +3 -2
  103. data/lib/splitclient-rb/engine/matchers/whitelist_matcher.rb +7 -5
  104. data/lib/splitclient-rb/engine/metrics/binary_search_latency_tracker.rb +3 -65
  105. data/lib/splitclient-rb/engine/models/evaluation_options.rb +9 -0
  106. data/lib/splitclient-rb/engine/models/event_active_subscriptions.rb +14 -0
  107. data/lib/splitclient-rb/engine/models/events_metadata.rb +10 -0
  108. data/lib/splitclient-rb/engine/models/fallback_treatment.rb +11 -0
  109. data/lib/splitclient-rb/engine/models/fallback_treatments_configuration.rb +36 -0
  110. data/lib/splitclient-rb/engine/models/label.rb +3 -0
  111. data/lib/splitclient-rb/engine/models/sdk_event.rb +4 -0
  112. data/lib/splitclient-rb/engine/models/sdk_event_type.rb +4 -0
  113. data/lib/splitclient-rb/engine/models/sdk_internal_event.rb +8 -0
  114. data/lib/splitclient-rb/engine/models/sdk_internal_event_notification.rb +14 -0
  115. data/lib/splitclient-rb/engine/models/segment_type.rb +4 -0
  116. data/lib/splitclient-rb/engine/models/split_http_response.rb +19 -0
  117. data/lib/splitclient-rb/engine/models/valid_sdk_event.rb +14 -0
  118. data/lib/splitclient-rb/engine/parser/condition.rb +81 -20
  119. data/lib/splitclient-rb/engine/parser/evaluator.rb +40 -51
  120. data/lib/splitclient-rb/engine/push_manager.rb +66 -0
  121. data/lib/splitclient-rb/engine/status_manager.rb +39 -0
  122. data/lib/splitclient-rb/engine/sync_manager.rb +180 -0
  123. data/lib/splitclient-rb/engine/synchronizer.rb +231 -0
  124. data/lib/splitclient-rb/exceptions.rb +20 -1
  125. data/lib/splitclient-rb/helpers/decryption_helper.rb +25 -0
  126. data/lib/splitclient-rb/helpers/evaluator_helper.rb +37 -0
  127. data/lib/splitclient-rb/helpers/repository_helper.rb +61 -0
  128. data/lib/splitclient-rb/helpers/thread_helper.rb +24 -0
  129. data/lib/splitclient-rb/helpers/util.rb +26 -0
  130. data/lib/splitclient-rb/managers/split_manager.rb +58 -20
  131. data/lib/splitclient-rb/spec.rb +9 -0
  132. data/lib/splitclient-rb/split_config.rb +336 -54
  133. data/lib/splitclient-rb/split_factory.rb +219 -33
  134. data/lib/splitclient-rb/split_factory_builder.rb +1 -22
  135. data/lib/splitclient-rb/split_factory_registry.rb +63 -0
  136. data/lib/splitclient-rb/split_logger.rb +9 -10
  137. data/lib/splitclient-rb/sse/event_source/client.rb +263 -0
  138. data/lib/splitclient-rb/sse/event_source/event_parser.rb +65 -0
  139. data/lib/splitclient-rb/sse/event_source/event_types.rb +15 -0
  140. data/lib/splitclient-rb/sse/event_source/stream_data.rb +22 -0
  141. data/lib/splitclient-rb/sse/notification_manager_keeper.rb +84 -0
  142. data/lib/splitclient-rb/sse/notification_processor.rb +48 -0
  143. data/lib/splitclient-rb/sse/sse_handler.rb +44 -0
  144. data/lib/splitclient-rb/sse/workers/segments_worker.rb +62 -0
  145. data/lib/splitclient-rb/sse/workers/splits_worker.rb +149 -0
  146. data/lib/splitclient-rb/telemetry/domain/constants.rb +48 -0
  147. data/lib/splitclient-rb/telemetry/domain/structs.rb +35 -0
  148. data/lib/splitclient-rb/telemetry/evaluation_consumer.rb +14 -0
  149. data/lib/splitclient-rb/telemetry/evaluation_producer.rb +21 -0
  150. data/lib/splitclient-rb/telemetry/init_consumer.rb +14 -0
  151. data/lib/splitclient-rb/telemetry/init_producer.rb +19 -0
  152. data/lib/splitclient-rb/telemetry/memory/memory_evaluation_consumer.rb +32 -0
  153. data/lib/splitclient-rb/telemetry/memory/memory_evaluation_producer.rb +24 -0
  154. data/lib/splitclient-rb/telemetry/memory/memory_init_consumer.rb +28 -0
  155. data/lib/splitclient-rb/telemetry/memory/memory_init_producer.rb +34 -0
  156. data/lib/splitclient-rb/telemetry/memory/memory_runtime_consumer.rb +119 -0
  157. data/lib/splitclient-rb/telemetry/memory/memory_runtime_producer.rb +87 -0
  158. data/lib/splitclient-rb/telemetry/memory/memory_synchronizer.rb +213 -0
  159. data/lib/splitclient-rb/telemetry/redis/redis_evaluation_producer.rb +38 -0
  160. data/lib/splitclient-rb/telemetry/redis/redis_init_producer.rb +37 -0
  161. data/lib/splitclient-rb/telemetry/redis/redis_synchronizer.rb +27 -0
  162. data/lib/splitclient-rb/telemetry/runtime_consumer.rb +25 -0
  163. data/lib/splitclient-rb/telemetry/runtime_producer.rb +25 -0
  164. data/lib/splitclient-rb/telemetry/storages/memory.rb +159 -0
  165. data/lib/splitclient-rb/telemetry/sync_task.rb +36 -0
  166. data/lib/splitclient-rb/telemetry/synchronizer.rb +33 -0
  167. data/lib/splitclient-rb/utilitites.rb +8 -0
  168. data/lib/splitclient-rb/validators.rb +142 -38
  169. data/lib/splitclient-rb/version.rb +1 -1
  170. data/lib/splitclient-rb.rb +101 -16
  171. data/sonar-project.properties +6 -0
  172. data/splitclient-rb.gemspec +28 -23
  173. metadata +262 -82
  174. data/.travis.yml +0 -11
  175. data/Appraisals +0 -10
  176. data/Detailed-README.md +0 -588
  177. data/NEWS +0 -141
  178. data/lib/splitclient-rb/cache/repositories/metrics/memory_repository.rb +0 -127
  179. data/lib/splitclient-rb/cache/repositories/metrics/redis_repository.rb +0 -96
  180. data/lib/splitclient-rb/cache/repositories/metrics_repository.rb +0 -21
  181. data/lib/splitclient-rb/cache/senders/metrics_sender.rb +0 -56
  182. data/lib/splitclient-rb/cache/stores/sdk_blocker.rb +0 -46
  183. data/lib/splitclient-rb/cache/stores/segment_store.rb +0 -81
  184. data/lib/splitclient-rb/cache/stores/split_store.rb +0 -102
  185. data/lib/splitclient-rb/clients/localhost_split_client.rb +0 -183
  186. data/lib/splitclient-rb/engine/api/faraday_adapter/patched_net_http_persistent.rb +0 -46
  187. data/lib/splitclient-rb/engine/api/metrics.rb +0 -60
  188. data/lib/splitclient-rb/engine/metrics/metrics.rb +0 -80
  189. data/lib/splitclient-rb/engine/parser/split_adapter.rb +0 -81
  190. data/lib/splitclient-rb/localhost_split_factory.rb +0 -13
  191. data/lib/splitclient-rb/localhost_utils.rb +0 -59
  192. data/lib/splitclient-rb/managers/localhost_split_manager.rb +0 -60
@@ -1,183 +0,0 @@
1
- module SplitIoClient
2
- class LocalhostSplitClient
3
- include SplitIoClient::LocalhostUtils
4
-
5
- #
6
- # variables to if the sdk is being used in localhost mode and store the list of features
7
- attr_reader :localhost_mode
8
- attr_reader :localhost_mode_features
9
-
10
- #
11
- # Creates a new split client instance that reads from the given splits file
12
- #
13
- # @param splits_file [File] file that contains some splits
14
- #
15
- # @return [LocalhostSplitIoClient] split.io localhost client instance
16
- def initialize(splits_file, reload_rate = nil)
17
- @localhost_mode = true
18
- @localhost_mode_features = []
19
- load_localhost_mode_features(splits_file, reload_rate)
20
- end
21
-
22
- #
23
- # method that returns the sdk gem version
24
- #
25
- # @return [string] version value for this sdk
26
- def self.sdk_version
27
- 'ruby-'+SplitIoClient::VERSION
28
- end
29
-
30
- #
31
- # obtains the treatments and configs for a given set of features
32
- #
33
- # @param key [string] evaluation key, only used with yaml split files
34
- # @param split_names [array] name of the features being validated
35
- # @param attributes [hash] kept for consistency with actual SDK client. Omitted in calls
36
- #
37
- # @return [hash] map of treatments (split_name, treatment)
38
- def get_treatments_with_config(key, split_names, attributes = nil)
39
- get_localhost_treatments(key, split_names, attributes, 'get_treatments_with_config')
40
- end
41
-
42
- #
43
- # obtains the treatments for a given set of features
44
- #
45
- # @param key [string] evaluation key, only used with yaml split files
46
- # @param split_names [array] name of the features being validated
47
- # @param attributes [hash] kept for consistency with actual SDK client. Omitted in calls
48
- #
49
- # @return [hash] map of treatments (split_name, treatment_name)
50
- def get_treatments(key, split_names, attributes = nil)
51
- treatments = get_localhost_treatments(key, split_names, attributes)
52
- return treatments if treatments.nil?
53
- keys = treatments.keys
54
- treats = treatments.map { |_,t| t[:treatment] }
55
- Hash[keys.zip(treats)]
56
- end
57
-
58
- #
59
- # obtains the treatment for a given feature
60
- #
61
- # @param key [string] evaluation key, only used with yaml split files
62
- # @param split_name [string] name of the feature that is being validated
63
- # @param attributes [hash] kept for consistency with actual SDK client. Omitted in calls
64
- #
65
- # @return [string] corresponding treatment
66
- def get_treatment(key, split_name, attributes = nil)
67
- get_localhost_treatment(key, split_name, attributes)[:treatment]
68
- end
69
-
70
- #
71
- # obtains the treatment and config for a given feature
72
- #
73
- # @param key [string] evaluation key, only used with yaml split files
74
- # @param split_name [string] name of the feature that is being validated
75
- # @param attributes [hash] kept for consistency with actual SDK client. Omitted in calls
76
- #
77
- # @return [hash] corresponding treatment and config
78
- def get_treatment_with_config(key, split_name, attributes = nil)
79
- get_localhost_treatment(key, split_name, attributes, 'get_treatment_with_config')
80
- end
81
-
82
- def track
83
- end
84
-
85
- private
86
-
87
- #
88
- # method to check if the sdk is running in localhost mode based on api key
89
- #
90
- # @return [boolean] True if is in localhost mode, false otherwise
91
- def is_localhost_mode?
92
- true
93
- end
94
-
95
- # @param key [string] evaluation key, only used with yaml split files
96
- # @param split_name [string] name of the feature that is being validated
97
- #
98
- # @return [Hash] corresponding treatment and config, control otherwise
99
- def get_localhost_treatment(key, split_name, attributes, calling_method = 'get_treatment')
100
- control_treatment = { label: Engine::Models::Label::EXCEPTION, treatment: SplitIoClient::Engine::Models::Treatment::CONTROL, config: nil }
101
- parsed_control_treatment = parsed_treatment(control_treatment)
102
-
103
- bucketing_key, matching_key = keys_from_key(key)
104
- return parsed_control_treatment unless SplitIoClient::Validators.valid_get_treatment_parameters(calling_method, key, split_name, matching_key, bucketing_key, attributes)
105
-
106
- sanitized_split_name = split_name.to_s.strip
107
-
108
- if split_name.to_s != sanitized_split_name
109
- SplitIoClient.configuration.logger.warn("get_treatment: split_name #{split_name} has extra whitespace, trimming")
110
- split_name = sanitized_split_name
111
- end
112
-
113
- treatment = @localhost_mode_features.select { |h| h[:feature] == split_name && has_key(h[:keys], key) }.last
114
-
115
- if treatment.nil?
116
- treatment = @localhost_mode_features.select { |h| h[:feature] == split_name && h[:keys] == nil }.last
117
- end
118
-
119
- if treatment && treatment[:treatment]
120
- {
121
- treatment: treatment[:treatment],
122
- config: treatment[:config]
123
- }
124
- else
125
- parsed_control_treatment
126
- end
127
- end
128
-
129
- def get_localhost_treatments(key, split_names, attributes = nil, calling_method = 'get_treatments')
130
- return nil unless SplitIoClient::Validators.valid_get_treatments_parameters(calling_method, split_names)
131
-
132
- sanitized_split_names = sanitize_split_names(calling_method, split_names)
133
-
134
- if sanitized_split_names.empty?
135
- SplitIoClient.configuration.logger.error("#{calling_method}: split_names must be a non-empty Array")
136
- return {}
137
- end
138
-
139
- split_names.each_with_object({}) do |split_name, memo|
140
- memo.merge!(split_name => get_treatment_with_config(key, split_name, attributes))
141
- end
142
- end
143
-
144
- def sanitize_split_names(calling_method, split_names)
145
- split_names.compact.uniq.select do |split_name|
146
- if (split_name.is_a?(String) || split_name.is_a?(Symbol)) && !split_name.empty?
147
- true
148
- elsif split_name.is_a?(String) && split_name.empty?
149
- SplitIoClient.configuration.logger.warn("#{calling_method}: you passed an empty split_name, split_name must be a non-empty String or a Symbol")
150
- false
151
- else
152
- SplitIoClient.configuration.logger.warn("#{calling_method}: you passed an invalid split_name, split_name must be a non-empty String or a Symbol")
153
- false
154
- end
155
- end
156
- end
157
-
158
- def parsed_treatment(treatment_data)
159
- {
160
- treatment: treatment_data[:treatment],
161
- config: treatment_data[:config]
162
- }
163
- end
164
-
165
- def has_key(keys, key)
166
- case keys
167
- when Array then keys.include? key
168
- when String then keys == key
169
- else
170
- false
171
- end
172
- end
173
-
174
- def keys_from_key(key)
175
- case key
176
- when Hash
177
- key.values_at(:bucketing_key, :matching_key).map { |k| k.nil? ? nil : k }
178
- else
179
- [nil, key].map { |k| k.nil? ? nil : k }
180
- end
181
- end
182
- end
183
- end
@@ -1,46 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SplitIoClient
4
- module FaradayAdapter
5
- class PatchedNetHttpPersistent < Faraday::Adapter::NetHttpPersistent
6
- ##
7
- # Borrowed directly from the latest `NetHttpPersistent` adapter implementation.
8
- #
9
- # https://github.com/lostisland/faraday/blob/master/lib/faraday/adapter/net_http_persistent.rb
10
- #
11
- def net_http_connection(env)
12
- @cached_connection ||=
13
- if Net::HTTP::Persistent.instance_method(:initialize).parameters.first == [:key, :name]
14
- Net::HTTP::Persistent.new(name: 'Faraday')
15
- else
16
- Net::HTTP::Persistent.new('Faraday')
17
- end
18
-
19
- proxy_uri = proxy_uri(env)
20
- @cached_connection.proxy = proxy_uri if @cached_connection.proxy_uri != proxy_uri
21
- @cached_connection
22
- end
23
-
24
- def proxy_uri(env)
25
- proxy_uri = nil
26
- if (proxy = env[:request][:proxy])
27
- proxy_uri = ::URI::HTTP === proxy[:uri] ? proxy[:uri].dup : ::URI.parse(proxy[:uri].to_s)
28
- proxy_uri.user = proxy_uri.password = nil
29
- # awful patch for net-http-persistent 2.8 not unescaping user/password
30
- (
31
- class << proxy_uri;
32
- self;
33
- end).class_eval do
34
- define_method(:user) { proxy[:user] }
35
- define_method(:password) { proxy[:password] }
36
- end if proxy[:user]
37
- end
38
- proxy_uri
39
- end
40
-
41
- def with_net_http_connection(env)
42
- yield net_http_connection(env)
43
- end
44
- end
45
- end
46
- end
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SplitIoClient
4
- module Api
5
- class Metrics < Client
6
- def initialize(api_key, metrics_repository)
7
- @api_key = api_key
8
- @metrics_repository = metrics_repository
9
- end
10
-
11
- def post
12
- post_latencies
13
- post_counts
14
- end
15
-
16
- private
17
-
18
- def post_latencies
19
- if @metrics_repository.latencies.empty?
20
- SplitLogger.log_if_debug('No latencies to report.')
21
- else
22
- @metrics_repository.latencies.each do |name, latencies|
23
- metrics_time = { name: name, latencies: latencies }
24
-
25
- response = post_api("#{SplitIoClient.configuration.events_uri}/metrics/time", @api_key, metrics_time)
26
-
27
- log_status(response, metrics_time.size)
28
- end
29
- end
30
-
31
- @metrics_repository.clear_latencies
32
- end
33
-
34
- def post_counts
35
- if @metrics_repository.counts.empty?
36
- SplitLogger.log_if_debug('No counts to report.')
37
- else
38
- @metrics_repository.counts.each do |name, count|
39
- metrics_count = { name: name, delta: count }
40
-
41
- response = post_api("#{SplitIoClient.configuration.events_uri}/metrics/counter", @api_key, metrics_count)
42
-
43
- log_status(response, metrics_count.size)
44
- end
45
- end
46
- @metrics_repository.clear_counts
47
- end
48
-
49
- def log_status(response, info_to_log)
50
- if response.success?
51
- SplitLogger.log_if_debug("Metric time reported: #{info_to_log}")
52
- else
53
- SplitLogger.log_error("Unexpected status code while posting time metrics: #{response.status}" \
54
- ' - Check your API key and base URI')
55
- raise 'Split SDK failed to connect to backend to post metrics'
56
- end
57
- end
58
- end
59
- end
60
- end
@@ -1,80 +0,0 @@
1
- module SplitIoClient
2
-
3
- #
4
- # class to handle cached metrics
5
- #
6
- class Metrics < NoMethodError
7
-
8
- @counter
9
- @delta
10
-
11
- #
12
- # cached latencies
13
- #
14
- # @return [object] array of latencies
15
- attr_accessor :latencies
16
-
17
- #
18
- # cached counts
19
- #
20
- # @return [object] array of counts
21
- attr_accessor :counts
22
-
23
- #
24
- # cached gauges
25
- #
26
- # @return [object] array of gauges
27
- attr_accessor :gauges
28
-
29
- #
30
- # quese size for cached arrays
31
- #
32
- # @return [int] queue size
33
- attr_accessor :queue_size
34
-
35
- def initialize(queue_size, repository)
36
- @queue_size = queue_size
37
- @binary_search = SplitIoClient::BinarySearchLatencyTracker.new
38
- @repository = repository
39
- end
40
-
41
- #
42
- # creates a new entry in the array for cached counts
43
- #
44
- # @param counter [string] name of the counter
45
- # @delta [int] value of the counter
46
- #
47
- # @return void
48
- def count(counter, delta)
49
- return if (delta <= 0) || counter.nil? || counter.strip.empty?
50
-
51
- @repository.add_count(counter, delta)
52
- end
53
-
54
- #
55
- # creates a new entry in the array for cached time metrics
56
- #
57
- # @param operation [string] name of the operation
58
- # @time_in_ms [number] time in miliseconds
59
- #
60
- # @return void
61
- def time(operation, time_in_ms)
62
- return if operation.nil? || operation.empty? || time_in_ms < 0
63
-
64
- @repository.add_latency(operation, time_in_ms, @binary_search)
65
- end
66
-
67
- #
68
- # creates a new entry in the array for cached gauges
69
- #
70
- # @param gauge [string] name of the gauge
71
- # @value [number] value of the gauge
72
- #
73
- # @return void
74
- def gauge(gauge, value)
75
- return if gauge.nil? || gauge.empty?
76
-
77
- @repository.add_gauge(gauge, value)
78
- end
79
- end
80
- end
@@ -1,81 +0,0 @@
1
- require 'json'
2
- require 'thread'
3
-
4
- include SplitIoClient::Cache::Stores
5
- include SplitIoClient::Cache::Senders
6
-
7
- module SplitIoClient
8
- #
9
- # acts as an api adapater to connect to split endpoints
10
- # uses a configuration object that can be modified when creating the client instance
11
- # also, uses safe threads to execute fetches and post give the time execution values from the config
12
- #
13
- class SplitAdapter < NoMethodError
14
- attr_reader :splits_repository, :segments_repository, :impressions_repository, :metrics
15
-
16
- #
17
- # Creates a new split api adapter instance that consumes split api endpoints
18
- #
19
- # @param api_key [String] the API key for your split account
20
- # @param splits_repository [SplitsRepository] SplitsRepository instance to store splits in
21
- # @param segments_repository [SegmentsRepository] SegmentsRepository instance to store segments in
22
- # @param impressions_repository [ImpressionsRepository] ImpressionsRepository instance to store impressions in
23
- # @param metrics_repository [MetricsRepository] MetricsRepository instance to store metrics in
24
- # @param sdk_blocker [SDKBlocker] SDKBlocker instance which blocks splits_repository/segments_repository
25
- #
26
- # @return [SplitIoClient] split.io client instance
27
- def initialize(
28
- api_key,
29
- splits_repository,
30
- segments_repository,
31
- impressions_repository,
32
- metrics_repository,
33
- events_repository,
34
- sdk_blocker
35
- )
36
- @api_key = api_key
37
- @splits_repository = splits_repository
38
- @segments_repository = segments_repository
39
- @impressions_repository = impressions_repository
40
- @metrics_repository = metrics_repository
41
- @events_repository = events_repository
42
- @metrics = Metrics.new(100, @metrics_repository)
43
- @sdk_blocker = sdk_blocker
44
-
45
- start_standalone_components if SplitIoClient.configuration.mode == :standalone
46
- end
47
-
48
- def start_standalone_components
49
- split_store
50
- segment_store
51
- metrics_sender
52
- impressions_sender
53
- events_sender
54
- end
55
-
56
- # Starts thread which loops constantly and stores splits in the splits_repository of choice
57
- def split_store
58
- SplitStore.new(@splits_repository, @api_key, @metrics, @sdk_blocker).call
59
- end
60
-
61
- # Starts thread which loops constantly and stores segments in the segments_repository of choice
62
- def segment_store
63
- SegmentStore.new(@segments_repository, @api_key, @metrics, @sdk_blocker).call
64
- end
65
-
66
- # Starts thread which loops constantly and sends impressions to the Split API
67
- def impressions_sender
68
- ImpressionsSender.new(@impressions_repository, @api_key).call
69
- end
70
-
71
- # Starts thread which loops constantly and sends metrics to the Split API
72
- def metrics_sender
73
- MetricsSender.new(@metrics_repository, @api_key).call
74
- end
75
-
76
- # Starts thread which loops constantly and sends events to the Split API
77
- def events_sender
78
- EventsSender.new(@events_repository, @api_key).call
79
- end
80
- end
81
- end
@@ -1,13 +0,0 @@
1
- module SplitIoClient
2
- class LocalhostSplitFactory
3
- attr_reader :client, :manager
4
-
5
- def initialize(splits_file, reload_rate = nil, logger = nil)
6
- @splits_file = splits_file
7
- @reload_rate = reload_rate
8
-
9
- @client = LocalhostSplitClient.new(@splits_file, @reload_rate)
10
- @manager = LocalhostSplitManager.new(@splits_file, @reload_rate)
11
- end
12
- end
13
- end
@@ -1,59 +0,0 @@
1
- module SplitIoClient
2
- module LocalhostUtils
3
-
4
- require 'yaml'
5
- #
6
- # method to set localhost mode features by reading the given .splits
7
- #
8
- # @param splits_file [File] the .split file that contains the splits
9
- # @param reload_rate [Integer] the number of seconds to reload splits_file
10
- # @return nil
11
- def load_localhost_mode_features(splits_file, reload_rate = nil)
12
- return @localhost_mode_features unless File.exists?(splits_file)
13
-
14
- store_features(splits_file)
15
-
16
- return unless reload_rate
17
-
18
- Thread.new do
19
- loop do
20
- @localhost_mode_features = []
21
- store_features(splits_file)
22
-
23
- sleep(SplitIoClient::Utilities.randomize_interval(reload_rate))
24
- end
25
- end
26
- end
27
-
28
- def store_features(splits_file)
29
- yaml_extensions = [".yml", ".yaml"]
30
- if yaml_extensions.include? File.extname(splits_file)
31
- store_yaml_features(splits_file)
32
- else
33
- store_plain_text_features(splits_file)
34
- end
35
- end
36
-
37
- private
38
-
39
- def store_plain_text_features(splits_file)
40
- File.open(splits_file).each do |line|
41
- feature, treatment = line.strip.split(' ')
42
-
43
- next if line.start_with?('#') || line.strip.empty?
44
-
45
- @localhost_mode_features << { feature: feature, treatment: treatment, key: nil, config: nil }
46
- end
47
- end
48
-
49
- def store_yaml_features(splits_file)
50
- YAML.load(File.read(splits_file)).each do |feature|
51
- feat_symbolized_keys = feature[feature.keys.first].inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
52
-
53
- feat_symbolized_keys[:config] = feat_symbolized_keys[:config].to_json
54
-
55
- @localhost_mode_features << { feature: feature.keys.first }.merge(feat_symbolized_keys)
56
- end
57
- end
58
- end
59
- end
@@ -1,60 +0,0 @@
1
- module SplitIoClient
2
- class LocalhostSplitManager
3
- include SplitIoClient::LocalhostUtils
4
-
5
- #
6
- # Creates a new split manager instance that holds the splits from a given file
7
- #
8
- # @param splits_file [File] the .split file that contains the splits
9
- # @param reload_rate [Integer] the number of seconds to reload splits_file
10
- #
11
- # @return [LocalhostSplitIoManager] split.io localhost manager instance
12
- def initialize(splits_file, reload_rate = nil)
13
- @localhost_mode = true
14
- @localhost_mode_features = []
15
-
16
- load_localhost_mode_features(splits_file, reload_rate)
17
- end
18
-
19
- #
20
- # method to get a split view
21
- #
22
- # @returns a split view
23
- def split(split_name)
24
- features = @localhost_mode_features.find_all { |feat| feat[:feature] == split_name }
25
-
26
- return nil if features.nil?
27
-
28
- treatments = features.map { |feat| feat[:treatment] }
29
-
30
- configs = Hash[ features.map { |feat| [ feat[:treatment].to_sym, feat[:config] ] } ]
31
-
32
- {
33
- change_number: nil,
34
- killed: false,
35
- name: split_name,
36
- traffic_type: nil,
37
- treatments: treatments,
38
- configs: configs
39
- }
40
- end
41
-
42
- #
43
- # method to get the split list from the client
44
- #
45
- # @returns Array of split view
46
- def splits
47
- split_names.map do |split_name|
48
- split(split_name)
49
- end
50
- end
51
-
52
- #
53
- # method to get the list of just split names. Ideal for ietrating and calling client.get_treatment
54
- #
55
- # @returns [object] array of split names (String)
56
- def split_names
57
- @localhost_mode_features.map{ |feat| feat[:feature]}.uniq
58
- end
59
- end
60
- end