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
data/NEWS DELETED
@@ -1,141 +0,0 @@
1
- 6.3.0 (Apr 30, 2019)
2
-
3
- - Added Dynamic Configurations support through two new methods that mimick the regular ones, changing the type of what is returned.
4
- - get_treatment_with_config: Same as get_treatment but returning the treatment with it's config.
5
- - get_treatments_with_config: Same as get_treatments, but instead of a map of string it returns a map of treatments with config.
6
- - Added configs to SplitViews returned by the manager module.
7
- - Updated localhost mode. Now besides supporting the old text files with `.split` extension (to be deprecated soon), we support YAML (.yaml/.yml) files where you can
8
- define configurations for your treatments and also whitelisted keys. Read more in our docs!
9
-
10
- 6.2.0
11
- Ensure SDK flushes information to Split servers on client destroy
12
- Fix for compatibility issue between Faraday < 0.13 and net-http-persistent 3
13
- Change default features refresh rate interval to 5 seconds
14
-
15
- 6.1.0
16
-
17
- Review input validation for client API methods: get_treatment, get_treatments, track, manager. Add input validation to block_until_ready, client startup, and destroy
18
- Add additional logging to the SDK Client in order to help debug matcher related issues
19
- Fix for issue causing redis_url parameter to be ignored
20
-
21
- 6.0.1
22
-
23
- Fix an issue in events and impressions API calls log messages introduced in 6.0.0
24
-
25
- 6.0.0
26
-
27
- BREAKING CHANGE: Remove producer mode, make memory adapter mandatory in standalone mode, and Redis adapter mandatory in consumer mode.
28
- BREAKING CHANGE: Reduce the total number of Redis operations of the SDK by changing the impressions storage format and adding a memory cache for splits and segments. It requires to have Split Synchronizer > v2.0.0 running if you are using Redis.
29
- SDK is now compatible with net-http-persistent 3.0.
30
-
31
- 5.1.2
32
-
33
- Add input validation for client API methods: get_treatment, get_treatments, track, manager
34
-
35
- 5.1.1
36
-
37
- Reduces the number of calls to Redis when calling #client.get_treatments using such cache adapter.
38
-
39
- 5.1.0
40
-
41
- Prevent unhandled exceptions from raising when API get calls fail on Segments and Treatments.
42
-
43
- 5.0.3
44
-
45
- Creates a new configuration parameter (impressions_bulk_size) to manage the max number of impressions sent to the Split backend on each post.
46
- Changes impressions_queue_size so that it manages only the queue size in the memory adapter.
47
- A backwards compatibility fail safe is included for users of previous SDK versions.
48
-
49
- 5.0.2
50
-
51
- Turn Impression Listener into an optional SDK feature.
52
- Prevents the impression thread from being started if a listener is not in place
53
-
54
- 5.0.1
55
-
56
- Adding stop! method to the factory.
57
- With this method the user will be able to stop the threads that queries the Split Service. This will be used in the before_fork configuration in Puma and Unicorn to stop the threads in the master process.
58
-
59
- 5.0.0
60
-
61
- This is a breaking change in how users buckets are allocated.
62
- Ruby SDK was wrongly picking up the right buckets and defauled to
63
- use a "legacy hashing" instead of our moder murmur3 algo which is
64
- what other SDKs use. Please reach out to support@split.io for help
65
- on how to upgrade to this release.
66
-
67
- 4.5.0
68
-
69
- Add JRuby support
70
-
71
- 4.4.0
72
-
73
- Add the ability to send event data to split service (.track() api)
74
-
75
- 4.3.0
76
-
77
- Add support for impression listener, there is an ability to use user-defined class to capture all impressions
78
- Now you can apply attribute matcher to the traffic type
79
-
80
- 4.2.0
81
-
82
- Introduce new matchers: boolean and regexp (string).
83
- Remove unneeded dependencies
84
- Introduce dependency matcher, which allows treatment of one split to depend on the evaluation of another.
85
-
86
- 4.1.0
87
-
88
- Introduce set matchers: part of set, contains all and contains any, starts with, ends with and contains.
89
-
90
- 4.0.0
91
-
92
- Add support for murmur3 hashing algorithm
93
- Optimize gem memory usage
94
-
95
- 3.3.0
96
-
97
- Add support for traffic allocation
98
-
99
- 3.1.0
100
-
101
- Now supporting Redis as a cache adapter
102
- Factory is build now as SplitIoClient::SplitFactoryBuilder.build('<API_KEY>')
103
-
104
- 3.0.2
105
-
106
- now support also client.get_treatment( { :matching_key = 'bb' , "bucketing_key = ''}, ....)
107
-
108
- 2.0.1
109
-
110
- No news for this release
111
-
112
- 2.0.0
113
-
114
- Instantiation of the split client is now through a factory:
115
-
116
- factory = SplitIoClient::SplitFactory.new("rbk5je8be5qflpa047m17fe4ra", options)
117
- client = factory.client
118
- manager = factory.manager
119
-
120
- 1.0.4
121
-
122
- Added AND combiner for conditions support. Added events_uri config param which is the url where the metrics post are send to.
123
-
124
- 1.0.3
125
-
126
- This version of the gem fixes two minor bugs related to the config option for the refresh rates, as well as an inconsistency for the split definitions that are not created from the web app, but directly from the api instead.
127
-
128
- 1.0.2
129
-
130
- Support for all the new matchers including: number comparison with >=, <=, =, between; date comparison with is on or before, is on or after, is on, between; attribute value in a defined set of values.
131
- No other major updates for this release.
132
-
133
- 1.0.1
134
-
135
- isTreatment was removed from the API
136
- local environment file was removed to match the rest of the SDKs. "split".
137
- No other major updates for this release.
138
-
139
- 1.0.0
140
-
141
- No news for this release.
@@ -1,127 +0,0 @@
1
- module SplitIoClient
2
- module Cache
3
- module Repositories
4
- module Metrics
5
- class MemoryRepository
6
- def initialize(_ = nil, adapter)
7
- @counts = []
8
- @latencies = []
9
- @gauges = []
10
- end
11
-
12
- def add_count(counter, delta)
13
- counter_hash = @counts.find { |c| c[:name] == counter }
14
- if counter_hash.nil?
15
- counter_delta = SumAndCount.new
16
- counter_delta.add_delta(delta)
17
- @counts << { name: counter, delta: counter_delta }
18
- else
19
- counter_hash[:delta].add_delta(delta)
20
- end
21
- end
22
-
23
- def add_latency(operation, time_in_ms, binary_search)
24
- operation_hash = @latencies.find { |l| l[:operation] == operation }
25
- if operation_hash.nil?
26
- latencies_for_op = (operation == 'sdk.get_treatment') ? binary_search.add_latency_millis(time_in_ms) : [time_in_ms]
27
- @latencies << { operation: operation, latencies: latencies_for_op }
28
- else
29
- latencies_for_op = (operation == 'sdk.get_treatment') ? binary_search.add_latency_millis(time_in_ms) : operation_hash[:latencies].push(time_in_ms)
30
- end
31
- end
32
-
33
- def add_gauge(gauge, value)
34
- gauge_hash = @gauges.find { |g| g[:name] == gauge }
35
- if gauge_hash.nil?
36
- gauge_value = ValueAndCount.new
37
- gauge_value.set_value(value)
38
- @gauges << { name: gauge, value: gauge_value }
39
- else
40
- gauge_hash[:value].set_value(value)
41
- end
42
- end
43
-
44
- def counts
45
- @counts.each_with_object({}) do |count, memo|
46
- memo[count[:name]] = count[:delta].sum
47
- end
48
- end
49
-
50
- def latencies
51
- @latencies.each_with_object({}) do |latency, memo|
52
- memo[latency[:operation]] = latency[:latencies]
53
- end
54
- end
55
-
56
- def gauges
57
- # TODO
58
- end
59
-
60
- def clear_counts
61
- @counts = []
62
- end
63
-
64
- def clear_latencies
65
- @latencies = []
66
- end
67
-
68
- def clear_gauges
69
- @gauges = []
70
- end
71
-
72
- def clear
73
- clear_counts
74
- clear_latencies
75
- clear_gauges
76
- end
77
-
78
- #
79
- # small class to act as DTO for counts
80
- #
81
- class SumAndCount
82
- attr_reader :count
83
- attr_reader :sum
84
-
85
- def initialize
86
- @count = 0
87
- @sum = 0
88
- end
89
-
90
- def add_delta(delta)
91
- @count += 1
92
- @sum += delta
93
- end
94
-
95
- def clear
96
- @count = 0
97
- @sum = 0
98
- end
99
- end
100
-
101
- #
102
- # small class to act as DTO for gauges
103
- #
104
- class ValueAndCount
105
- attr_reader :count
106
- attr_reader :value
107
-
108
- def initialize
109
- @count = 0
110
- @value = 0
111
- end
112
-
113
- def set_value(value)
114
- @count += 1
115
- @value = value
116
- end
117
-
118
- def clear
119
- @count = 0
120
- @value = 0
121
- end
122
- end
123
- end
124
- end
125
- end
126
- end
127
- end
@@ -1,96 +0,0 @@
1
- module SplitIoClient
2
- module Cache
3
- module Repositories
4
- module Metrics
5
- class RedisRepository < Repository
6
- def initialize(adapter = nil)
7
- @adapter = adapter
8
- end
9
-
10
- def add_count(counter, delta)
11
- prefixed_name = impressions_metrics_key("count.#{counter}")
12
- counts = @adapter.find_strings_by_prefix(prefixed_name)
13
-
14
- @adapter.inc(prefixed_name, delta)
15
- end
16
-
17
- def add_latency(operation, time_in_ms, binary_search)
18
- prefixed_name = impressions_metrics_key("latency.#{operation}")
19
-
20
- if operation == 'sdk.get_treatment'
21
- @adapter.inc("#{prefixed_name}.#{binary_search.add_latency_millis(time_in_ms, true)}")
22
- return
23
- end
24
-
25
- @adapter.append_to_string(prefixed_name, "#{time_in_ms},")
26
- end
27
-
28
- def add_gauge(gauge, value)
29
- # TODO
30
- end
31
-
32
- def counts
33
- keys = @adapter.find_strings_by_prefix(impressions_metrics_key("count"))
34
-
35
- return [] if keys.empty?
36
-
37
- @adapter.multiple_strings(keys).map do |name, data|
38
- [name.gsub(impressions_metrics_key('count.'), ''), data]
39
- end.to_h
40
- end
41
-
42
- def latencies
43
- collected_latencies = {}
44
- latencies_array = Array.new(BinarySearchLatencyTracker::BUCKETS.length, 0)
45
- keys = @adapter.find_strings_by_prefix(impressions_metrics_key('latency'))
46
-
47
- return [] if keys.empty?
48
-
49
- found_latencies = @adapter.multiple_strings(keys).map do |name, data|
50
- [name.gsub(impressions_metrics_key('latency.'), ''), data]
51
- end.to_h
52
-
53
- found_latencies.each do |key, value|
54
- if key.start_with?('sdk.get_treatment')
55
- index = key.gsub('sdk.get_treatment.', '').to_i
56
- latencies_array[index] = value.to_i
57
-
58
- next
59
- end
60
-
61
- collected_latencies[key] = value.split(',').map(&:to_f)
62
- end
63
-
64
- collected_latencies['sdk.get_treatment'] = latencies_array unless latencies_array.reduce(:+) == 0
65
-
66
- collected_latencies
67
- end
68
-
69
- def gauges
70
- # TODO
71
- end
72
-
73
- def clear_counts
74
- keys = @adapter.find_strings_by_prefix(impressions_metrics_key('count'))
75
- @adapter.delete(keys)
76
- end
77
-
78
- def clear_latencies
79
- keys = @adapter.find_strings_by_prefix(impressions_metrics_key('latency'))
80
- @adapter.delete(keys)
81
- end
82
-
83
- def clear_gauges
84
- # TODO
85
- end
86
-
87
- def clear
88
- clear_counts
89
- clear_latencies
90
- clear_gauges
91
- end
92
- end
93
- end
94
- end
95
- end
96
- end
@@ -1,21 +0,0 @@
1
- module SplitIoClient
2
- module Cache
3
- module Repositories
4
- # Repository which forwards impressions interface to the selected adapter
5
- class MetricsRepository < Repository
6
- extend Forwardable
7
- def_delegators :@adapter, :add_count, :add_latency, :add_gauge, :counts, :latencies, :gauges,
8
- :clear_counts, :clear_latencies, :clear_gauges, :clear
9
-
10
- def initialize(adapter)
11
- @adapter = case adapter.class.to_s
12
- when 'SplitIoClient::Cache::Adapters::MemoryAdapter'
13
- Repositories::Metrics::MemoryRepository.new(adapter)
14
- when 'SplitIoClient::Cache::Adapters::RedisAdapter'
15
- Repositories::Metrics::RedisRepository.new(adapter)
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end
@@ -1,56 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module SplitIoClient
4
- module Cache
5
- module Senders
6
- class MetricsSender
7
- def initialize(metrics_repository, api_key)
8
- @metrics_repository = metrics_repository
9
- @api_key = api_key
10
- end
11
-
12
- def call
13
- return if ENV['SPLITCLIENT_ENV'] == 'test'
14
-
15
- metrics_thread
16
-
17
- if defined?(PhusionPassenger)
18
- PhusionPassenger.on_event(:starting_worker_process) do |forked|
19
- metrics_thread if forked
20
- end
21
- end
22
- end
23
-
24
- private
25
-
26
- def metrics_thread
27
- SplitIoClient.configuration.threads[:metrics_sender] = Thread.new do
28
- begin
29
- SplitIoClient.configuration.logger.info('Starting metrics service')
30
-
31
- loop do
32
- post_metrics
33
-
34
- sleep(SplitIoClient::Utilities.randomize_interval(SplitIoClient.configuration.metrics_refresh_rate))
35
- end
36
- rescue SplitIoClient::SDKShutdownException
37
- post_metrics
38
-
39
- SplitIoClient.configuration.logger.info('Posting metrics due to shutdown')
40
- end
41
- end
42
- end
43
-
44
- def post_metrics
45
- metrics_api.post
46
- rescue StandardError => error
47
- SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
48
- end
49
-
50
- def metrics_api
51
- @metrics_api ||= SplitIoClient::Api::Metrics.new(@api_key, @metrics_repository)
52
- end
53
- end
54
- end
55
- end
56
- end
@@ -1,46 +0,0 @@
1
- require 'thread'
2
- require 'timeout'
3
-
4
- module SplitIoClient
5
- module Cache
6
- module Stores
7
- class SDKBlocker
8
- attr_reader :splits_repository
9
-
10
- def initialize(splits_repository, segments_repository)
11
- @splits_repository = splits_repository
12
- @segments_repository = segments_repository
13
-
14
- @splits_repository.not_ready!
15
- @segments_repository.not_ready!
16
- end
17
-
18
- def splits_ready!
19
- @splits_repository.ready!
20
- end
21
-
22
- def segments_ready!
23
- @segments_repository.ready!
24
- end
25
-
26
- def block
27
- begin
28
- Timeout::timeout(SplitIoClient.configuration.block_until_ready) do
29
- sleep 0.1 until ready?
30
- end
31
- rescue Timeout::Error
32
- fail SDKBlockerTimeoutExpiredException, 'SDK start up timeout expired'
33
- end
34
-
35
- SplitIoClient.configuration.logger.info('SplitIO SDK is ready')
36
- SplitIoClient.configuration.threads[:split_store].run
37
- SplitIoClient.configuration.threads[:segment_store].run
38
- end
39
-
40
- def ready?
41
- @splits_repository.ready? && @segments_repository.ready?
42
- end
43
- end
44
- end
45
- end
46
- end
@@ -1,81 +0,0 @@
1
- module SplitIoClient
2
- module Cache
3
- module Stores
4
- class SegmentStore
5
- attr_reader :segments_repository
6
-
7
- def initialize(segments_repository, api_key, metrics, sdk_blocker = nil)
8
- @segments_repository = segments_repository
9
- @api_key = api_key
10
- @metrics = metrics
11
- @sdk_blocker = sdk_blocker
12
- end
13
-
14
- def call
15
- if ENV['SPLITCLIENT_ENV'] == 'test'
16
- store_segments
17
- else
18
- segments_thread
19
-
20
- if defined?(PhusionPassenger)
21
- PhusionPassenger.on_event(:starting_worker_process) do |forked|
22
- segments_thread if forked
23
- end
24
- end
25
- end
26
- end
27
-
28
- private
29
-
30
- def segments_thread
31
- SplitIoClient.configuration.threads[:segment_store] = Thread.new do
32
- SplitIoClient.configuration.logger.info('Starting segments fetcher service')
33
- SplitIoClient.configuration.block_until_ready > 0 ? blocked_store : unblocked_store
34
- end
35
- end
36
-
37
- def blocked_store
38
- loop do
39
- next unless @sdk_blocker.splits_repository.ready?
40
-
41
- store_segments
42
- SplitIoClient.configuration.logger.debug("Segment names: #{@segments_repository.used_segment_names.to_a}") if SplitIoClient.configuration.debug_enabled
43
-
44
- unless @sdk_blocker.ready?
45
- @sdk_blocker.segments_ready!
46
- SplitIoClient.configuration.logger.info('segments are ready')
47
- end
48
-
49
- sleep_for = random_interval(SplitIoClient.configuration.segments_refresh_rate)
50
- SplitIoClient.configuration.logger.debug("Segments store is sleeping for: #{sleep_for} seconds") if SplitIoClient.configuration.debug_enabled
51
- sleep(sleep_for)
52
- end
53
- end
54
-
55
- def unblocked_store
56
- loop do
57
- store_segments
58
-
59
- sleep(random_interval(SplitIoClient.configuration.segments_refresh_rate))
60
- end
61
- end
62
-
63
- def store_segments
64
- segments_api.store_segments_by_names(@segments_repository.used_segment_names)
65
- rescue StandardError => error
66
- SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
67
- end
68
-
69
- def random_interval(interval)
70
- random_factor = Random.new.rand(50..100) / 100.0
71
-
72
- interval * random_factor
73
- end
74
-
75
- def segments_api
76
- @segments_api ||= SplitIoClient::Api::Segments.new(@api_key, @metrics, @segments_repository)
77
- end
78
- end
79
- end
80
- end
81
- end
@@ -1,102 +0,0 @@
1
- module SplitIoClient
2
- module Cache
3
- module Stores
4
- class SplitStore
5
- attr_reader :splits_repository
6
-
7
- def initialize(splits_repository, api_key, metrics, sdk_blocker = nil)
8
- @splits_repository = splits_repository
9
- @api_key = api_key
10
- @metrics = metrics
11
- @sdk_blocker = sdk_blocker
12
- end
13
-
14
- def call
15
- if ENV['SPLITCLIENT_ENV'] == 'test'
16
- store_splits
17
- else
18
- splits_thread
19
-
20
- if defined?(PhusionPassenger)
21
- PhusionPassenger.on_event(:starting_worker_process) do |forked|
22
- splits_thread if forked
23
- end
24
- end
25
- end
26
- end
27
-
28
- private
29
-
30
- def splits_thread
31
- SplitIoClient.configuration.threads[:split_store] = Thread.new do
32
- SplitIoClient.configuration.logger.info('Starting splits fetcher service')
33
- loop do
34
- store_splits
35
-
36
- sleep(random_interval(SplitIoClient.configuration.features_refresh_rate))
37
- end
38
- end
39
- end
40
-
41
- def store_splits
42
- data = splits_since(@splits_repository.get_change_number)
43
-
44
- data[:splits] && data[:splits].each do |split|
45
- add_split_unless_archived(split)
46
- end
47
-
48
- @splits_repository.set_segment_names(data[:segment_names])
49
- @splits_repository.set_change_number(data[:till])
50
-
51
- SplitIoClient.configuration.logger.debug("segments seen(#{data[:segment_names].length}): #{data[:segment_names].to_a}") if SplitIoClient.configuration.debug_enabled
52
-
53
- if SplitIoClient.configuration.block_until_ready > 0 && !@sdk_blocker.ready?
54
- @sdk_blocker.splits_ready!
55
- SplitIoClient.configuration.logger.info('splits are ready')
56
- end
57
-
58
- rescue StandardError => error
59
- SplitIoClient.configuration.log_found_exception(__method__.to_s, error)
60
- end
61
-
62
- def random_interval(interval)
63
- random_factor = Random.new.rand(50..100) / 100.0
64
-
65
- interval * random_factor
66
- end
67
-
68
- def splits_since(since)
69
- splits_api.since(since)
70
- end
71
-
72
- def add_split_unless_archived(split)
73
- if Engine::Models::Split.archived?(split)
74
- SplitIoClient.configuration.logger.debug("Seeing archived split #{split[:name]}") if SplitIoClient.configuration.debug_enabled
75
-
76
- remove_archived_split(split)
77
- else
78
- store_split(split)
79
- end
80
- end
81
-
82
- def remove_archived_split(split)
83
- SplitIoClient.configuration.logger.debug("removing split from store(#{split})") if SplitIoClient.configuration.debug_enabled
84
-
85
- @splits_repository.remove_split(split[:name])
86
- end
87
-
88
- def store_split(split)
89
- SplitIoClient.configuration.logger.debug("storing split (#{split[:name]})") if SplitIoClient.configuration.debug_enabled
90
-
91
- @splits_repository.add_split(split)
92
- end
93
-
94
- private
95
-
96
- def splits_api
97
- @splits_api ||= SplitIoClient::Api::Splits.new(@api_key, @metrics)
98
- end
99
- end
100
- end
101
- end
102
- end