optimizely-sdk 5.0.0.pre.beta → 5.0.1

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 (64) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +202 -202
  3. data/lib/optimizely/audience.rb +127 -127
  4. data/lib/optimizely/bucketer.rb +156 -156
  5. data/lib/optimizely/condition_tree_evaluator.rb +123 -123
  6. data/lib/optimizely/config/datafile_project_config.rb +48 -32
  7. data/lib/optimizely/config/proxy_config.rb +34 -34
  8. data/lib/optimizely/config_manager/async_scheduler.rb +95 -95
  9. data/lib/optimizely/config_manager/http_project_config_manager.rb +340 -338
  10. data/lib/optimizely/config_manager/project_config_manager.rb +25 -25
  11. data/lib/optimizely/config_manager/static_project_config_manager.rb +55 -54
  12. data/lib/optimizely/decide/optimizely_decide_option.rb +28 -28
  13. data/lib/optimizely/decide/optimizely_decision.rb +60 -60
  14. data/lib/optimizely/decide/optimizely_decision_message.rb +26 -26
  15. data/lib/optimizely/decision_service.rb +563 -563
  16. data/lib/optimizely/error_handler.rb +39 -39
  17. data/lib/optimizely/event/batch_event_processor.rb +235 -235
  18. data/lib/optimizely/event/entity/conversion_event.rb +44 -44
  19. data/lib/optimizely/event/entity/decision.rb +38 -38
  20. data/lib/optimizely/event/entity/event_batch.rb +86 -86
  21. data/lib/optimizely/event/entity/event_context.rb +50 -50
  22. data/lib/optimizely/event/entity/impression_event.rb +48 -48
  23. data/lib/optimizely/event/entity/snapshot.rb +33 -33
  24. data/lib/optimizely/event/entity/snapshot_event.rb +48 -48
  25. data/lib/optimizely/event/entity/user_event.rb +22 -22
  26. data/lib/optimizely/event/entity/visitor.rb +36 -36
  27. data/lib/optimizely/event/entity/visitor_attribute.rb +38 -38
  28. data/lib/optimizely/event/event_factory.rb +156 -156
  29. data/lib/optimizely/event/event_processor.rb +25 -25
  30. data/lib/optimizely/event/forwarding_event_processor.rb +44 -44
  31. data/lib/optimizely/event/user_event_factory.rb +88 -88
  32. data/lib/optimizely/event_builder.rb +221 -221
  33. data/lib/optimizely/event_dispatcher.rb +69 -69
  34. data/lib/optimizely/exceptions.rb +193 -149
  35. data/lib/optimizely/helpers/constants.rb +459 -459
  36. data/lib/optimizely/helpers/date_time_utils.rb +30 -30
  37. data/lib/optimizely/helpers/event_tag_utils.rb +132 -132
  38. data/lib/optimizely/helpers/group.rb +31 -31
  39. data/lib/optimizely/helpers/http_utils.rb +68 -68
  40. data/lib/optimizely/helpers/sdk_settings.rb +61 -61
  41. data/lib/optimizely/helpers/validator.rb +236 -238
  42. data/lib/optimizely/helpers/variable_type.rb +67 -67
  43. data/lib/optimizely/logger.rb +46 -46
  44. data/lib/optimizely/notification_center.rb +174 -174
  45. data/lib/optimizely/notification_center_registry.rb +71 -71
  46. data/lib/optimizely/odp/lru_cache.rb +114 -114
  47. data/lib/optimizely/odp/odp_config.rb +102 -102
  48. data/lib/optimizely/odp/odp_event.rb +75 -75
  49. data/lib/optimizely/odp/odp_event_api_manager.rb +70 -70
  50. data/lib/optimizely/odp/odp_event_manager.rb +286 -286
  51. data/lib/optimizely/odp/odp_manager.rb +159 -159
  52. data/lib/optimizely/odp/odp_segment_api_manager.rb +122 -122
  53. data/lib/optimizely/odp/odp_segment_manager.rb +97 -97
  54. data/lib/optimizely/optimizely_config.rb +273 -271
  55. data/lib/optimizely/optimizely_factory.rb +184 -186
  56. data/lib/optimizely/optimizely_user_context.rb +238 -238
  57. data/lib/optimizely/params.rb +31 -31
  58. data/lib/optimizely/project_config.rb +99 -99
  59. data/lib/optimizely/semantic_version.rb +166 -166
  60. data/lib/optimizely/user_condition_evaluator.rb +391 -391
  61. data/lib/optimizely/user_profile_service.rb +35 -35
  62. data/lib/optimizely/version.rb +21 -21
  63. data/lib/optimizely.rb +1262 -1262
  64. metadata +12 -10
@@ -1,69 +1,69 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2016-2017, 2019-2020, 2022 Optimizely and contributors
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
- require_relative 'exceptions'
19
- require_relative 'helpers/http_utils'
20
- require_relative 'helpers/constants'
21
-
22
- module Optimizely
23
- class NoOpEventDispatcher
24
- # Class providing dispatch_event method which does nothing.
25
-
26
- def dispatch_event(event); end
27
- end
28
-
29
- class EventDispatcher
30
- def initialize(logger: nil, error_handler: nil, proxy_config: nil)
31
- @logger = logger || NoOpLogger.new
32
- @error_handler = error_handler || NoOpErrorHandler.new
33
- @proxy_config = proxy_config
34
- end
35
-
36
- # Dispatch the event being represented by the Event object.
37
- #
38
- # @param event - Event object
39
- def dispatch_event(event)
40
- response = Helpers::HttpUtils.make_request(
41
- event.url, event.http_verb, event.params.to_json, event.headers, Helpers::Constants::EVENT_DISPATCH_CONFIG[:REQUEST_TIMEOUT], @proxy_config
42
- )
43
-
44
- error_msg = "Event failed to dispatch with response code: #{response.code}"
45
-
46
- case response.code.to_i
47
- when 400...500
48
- @logger.log(Logger::ERROR, error_msg)
49
- @error_handler.handle_error(HTTPCallError.new("HTTP Client Error: #{response.code}"))
50
-
51
- when 500...600
52
- @logger.log(Logger::ERROR, error_msg)
53
- @error_handler.handle_error(HTTPCallError.new("HTTP Server Error: #{response.code}"))
54
- else
55
- @logger.log(Logger::DEBUG, "event successfully sent with response code #{response.code}")
56
- end
57
- rescue Timeout::Error => e
58
- @logger.log(Logger::ERROR, "Request Timed out. Error: #{e}")
59
- @error_handler.handle_error(e)
60
-
61
- # Returning Timeout error to retain existing behavior.
62
- e
63
- rescue StandardError => e
64
- @logger.log(Logger::ERROR, "Event failed to dispatch. Error: #{e}")
65
- @error_handler.handle_error(e)
66
- nil
67
- end
68
- end
69
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2016-2017, 2019-2020, 2022 Optimizely and contributors
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ require_relative 'exceptions'
19
+ require_relative 'helpers/http_utils'
20
+ require_relative 'helpers/constants'
21
+
22
+ module Optimizely
23
+ class NoOpEventDispatcher
24
+ # Class providing dispatch_event method which does nothing.
25
+
26
+ def dispatch_event(event); end
27
+ end
28
+
29
+ class EventDispatcher
30
+ def initialize(logger: nil, error_handler: nil, proxy_config: nil)
31
+ @logger = logger || NoOpLogger.new
32
+ @error_handler = error_handler || NoOpErrorHandler.new
33
+ @proxy_config = proxy_config
34
+ end
35
+
36
+ # Dispatch the event being represented by the Event object.
37
+ #
38
+ # @param event - Event object
39
+ def dispatch_event(event)
40
+ response = Helpers::HttpUtils.make_request(
41
+ event.url, event.http_verb, event.params.to_json, event.headers, Helpers::Constants::EVENT_DISPATCH_CONFIG[:REQUEST_TIMEOUT], @proxy_config
42
+ )
43
+
44
+ error_msg = "Event failed to dispatch with response code: #{response.code}"
45
+
46
+ case response.code.to_i
47
+ when 400...500
48
+ @logger.log(Logger::ERROR, error_msg)
49
+ @error_handler.handle_error(HTTPCallError.new("HTTP Client Error: #{response.code}"))
50
+
51
+ when 500...600
52
+ @logger.log(Logger::ERROR, error_msg)
53
+ @error_handler.handle_error(HTTPCallError.new("HTTP Server Error: #{response.code}"))
54
+ else
55
+ @logger.log(Logger::DEBUG, "event successfully sent with response code #{response.code}")
56
+ end
57
+ rescue Timeout::Error => e
58
+ @logger.log(Logger::ERROR, "Request Timed out. Error: #{e}")
59
+ @error_handler.handle_error(e)
60
+
61
+ # Returning Timeout error to retain existing behavior.
62
+ e
63
+ rescue StandardError => e
64
+ @logger.log(Logger::ERROR, "Event failed to dispatch. Error: #{e}")
65
+ @error_handler.handle_error(e)
66
+ nil
67
+ end
68
+ end
69
+ end
@@ -1,149 +1,193 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2016-2020, 2022-2023, Optimizely and contributors
5
- #
6
- # Licensed under the Apache License, Version 2.0 (the "License");
7
- # you may not use this file except in compliance with the License.
8
- # You may obtain a copy of the License at
9
- #
10
- # http://www.apache.org/licenses/LICENSE-2.0
11
- #
12
- # Unless required by applicable law or agreed to in writing, software
13
- # distributed under the License is distributed on an "AS IS" BASIS,
14
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
- # See the License for the specific language governing permissions and
16
- # limitations under the License.
17
- #
18
- module Optimizely
19
- class Error < StandardError; end
20
-
21
- class HTTPCallError < Error
22
- # Raised when a 4xx or 5xx response code is recieved.
23
- def initialize(msg = 'HTTP call resulted in a response with an error code.')
24
- super
25
- end
26
- end
27
-
28
- class HTTPUriError < Error
29
- # Raised when a provided URI is invalid.
30
- def initialize(msg = 'Provided URI was invalid.')
31
- super
32
- end
33
- end
34
-
35
- class MissingSdkKeyError < Error
36
- # Raised when a provided URI is invalid.
37
- def initialize(msg = 'SDK key not provided/cannot be found in the datafile.')
38
- super
39
- end
40
- end
41
-
42
- class InvalidAudienceError < Error
43
- # Raised when an invalid audience is provided
44
-
45
- def initialize(msg = 'Provided audience is not in datafile.')
46
- super
47
- end
48
- end
49
-
50
- class InvalidAttributeError < Error
51
- # Raised when an invalid attribute is provided
52
-
53
- def initialize(msg = 'Provided attribute is not in datafile.')
54
- super
55
- end
56
- end
57
-
58
- class InvalidAttributeFormatError < Error
59
- # Raised when attributes are provided in an invalid format (e.g. not a Hash)
60
-
61
- def initialize(msg = 'Attributes provided are in an invalid format.')
62
- super
63
- end
64
- end
65
-
66
- class InvalidEventTagFormatError < Error
67
- # Raised when attributes are provided in an invalid format (e.g. not a Hash)
68
-
69
- def initialize(msg = 'Event tags provided are in an invalid format.')
70
- super
71
- end
72
- end
73
-
74
- class InvalidExperimentError < Error
75
- # Raised when an invalid experiment key is provided
76
-
77
- def initialize(msg = 'Provided experiment is not in datafile.')
78
- super
79
- end
80
- end
81
-
82
- class InvalidEventError < Error
83
- # Raised when an invalid event key is provided
84
-
85
- def initialize(msg = 'Provided event is not in datafile.')
86
- super
87
- end
88
- end
89
-
90
- class InvalidVariationError < Error
91
- # Raised when an invalid variation key or ID is provided
92
-
93
- def initialize(msg = 'Provided variation is not in datafile.')
94
- super
95
- end
96
- end
97
-
98
- class InvalidDatafileVersionError < Error
99
- # Raised when a datafile with an unsupported version is provided
100
-
101
- def initialize(version)
102
- super("This version of the Ruby SDK does not support the given datafile version: #{version}.")
103
- end
104
- end
105
-
106
- class InvalidInputError < Error
107
- # Abstract error raised when an invalid input is provided during Project instantiation
108
-
109
- def initialize(type)
110
- super("Provided #{type} is in an invalid format.")
111
- end
112
- end
113
-
114
- class InvalidNotificationType < Error
115
- # Raised when an invalid notification type is provided
116
-
117
- def initialize(msg = 'Provided notification type is invalid.')
118
- super
119
- end
120
- end
121
-
122
- class InvalidInputsError < Error
123
- # Raised when an invalid inputs are provided during Project instantiation
124
- end
125
-
126
- class InvalidProjectConfigError < Error
127
- # Raised when a public method fails due to an invalid datafile
128
-
129
- def initialize(aborted_method)
130
- super("Optimizely instance is not valid. Failing '#{aborted_method}'.")
131
- end
132
- end
133
-
134
- class InvalidAttributeType < Error
135
- # Raised when an attribute is not provided in expected type.
136
-
137
- def initialize(msg = 'Provided attribute value is not in the expected data type.')
138
- super
139
- end
140
- end
141
-
142
- class InvalidSemanticVersion < Error
143
- # Raised when an invalid value is provided as semantic version.
144
-
145
- def initialize(msg = 'Provided semantic version is invalid.')
146
- super
147
- end
148
- end
149
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2016-2020, 2022-2023, Optimizely and contributors
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ module Optimizely
19
+ class Error < StandardError; end
20
+
21
+ class HTTPCallError < Error
22
+ # Raised when a 4xx or 5xx response code is recieved.
23
+ def initialize(msg = 'HTTP call resulted in a response with an error code.')
24
+ super
25
+ end
26
+ end
27
+
28
+ class HTTPUriError < Error
29
+ # Raised when a provided URI is invalid.
30
+ def initialize(msg = 'Provided URI was invalid.')
31
+ super
32
+ end
33
+ end
34
+
35
+ class MissingSdkKeyError < Error
36
+ # Raised when a provided URI is invalid.
37
+ def initialize(msg = 'SDK key not provided/cannot be found in the datafile.')
38
+ super
39
+ end
40
+ end
41
+
42
+ class InvalidAudienceError < Error
43
+ # Raised when an invalid audience is provided
44
+
45
+ attr_reader :audience_id
46
+
47
+ def initialize(audience_id)
48
+ raise ArgumentError, 'audience_id must be provided' if audience_id.nil?
49
+
50
+ super("Audience id '#{audience_id}' is not in datafile.")
51
+
52
+ @audience_id = audience_id
53
+ end
54
+ end
55
+
56
+ class InvalidAttributeError < Error
57
+ # Raised when an invalid attribute is provided
58
+
59
+ attr_reader :attribute_key
60
+
61
+ def initialize(attribute_key)
62
+ raise ArgumentError, 'attribute_key must be provided' if attribute_key.nil?
63
+
64
+ super("Attribute key '#{attribute_key}' is not in datafile.")
65
+
66
+ @attribute_key = attribute_key
67
+ end
68
+ end
69
+
70
+ class InvalidAttributeFormatError < Error
71
+ # Raised when attributes are provided in an invalid format (e.g. not a Hash)
72
+
73
+ def initialize(msg = 'Attributes provided are in an invalid format.')
74
+ super
75
+ end
76
+ end
77
+
78
+ class InvalidEventTagFormatError < Error
79
+ # Raised when attributes are provided in an invalid format (e.g. not a Hash)
80
+
81
+ def initialize(msg = 'Event tags provided are in an invalid format.')
82
+ super
83
+ end
84
+ end
85
+
86
+ class InvalidExperimentError < Error
87
+ # Raised when an invalid experiment key is provided
88
+
89
+ attr_reader :experiment_id, :experiment_key
90
+
91
+ def initialize(experiment_id: nil, experiment_key: nil)
92
+ raise ArgumentError, 'Either experiment_id or experiment_key must be provided.' if experiment_id.nil? && experiment_key.nil?
93
+ raise ArgumentError, 'Cannot provide both experiment_id and experiment_key.' if !experiment_id.nil? && !experiment_key.nil?
94
+
95
+ if experiment_id.nil?
96
+ @experiment_key = experiment_key
97
+ identifier = "key '#{@experiment_key}'"
98
+ else
99
+ @experiment_id = experiment_id
100
+ identifier = "id '#{@experiment_id}'"
101
+ end
102
+
103
+ super("Experiment #{identifier} is not in datafile.")
104
+ end
105
+ end
106
+
107
+ class InvalidEventError < Error
108
+ # Raised when an invalid event key is provided
109
+
110
+ attr_reader :event_key
111
+
112
+ def initialize(event_key)
113
+ raise ArgumentError, 'event_key must be provided.' if event_key.nil?
114
+
115
+ super("Event key '#{event_key}' is not in datafile.")
116
+
117
+ @event_key = event_key
118
+ end
119
+ end
120
+
121
+ class InvalidVariationError < Error
122
+ # Raised when an invalid variation key or ID is provided
123
+
124
+ attr_reader :variation_id, :variation_key
125
+
126
+ def initialize(variation_id: nil, variation_key: nil)
127
+ raise ArgumentError, 'Either variation_id or variation_key must be provided.' if variation_id.nil? && variation_key.nil?
128
+ raise ArgumentError, 'Cannot provide both variation_id and variation_key.' if !variation_id.nil? && !variation_key.nil?
129
+
130
+ if variation_id.nil?
131
+ identifier = "key '#{variation_key}'"
132
+ @variation_key = variation_key
133
+ else
134
+ identifier = "id '#{variation_id}'"
135
+ @variation_id = variation_id
136
+ end
137
+
138
+ super("Variation #{identifier} is not in datafile.")
139
+ end
140
+ end
141
+
142
+ class InvalidDatafileVersionError < Error
143
+ # Raised when a datafile with an unsupported version is provided
144
+
145
+ def initialize(version)
146
+ super("This version of the Ruby SDK does not support the given datafile version: #{version}.")
147
+ end
148
+ end
149
+
150
+ class InvalidInputError < Error
151
+ # Abstract error raised when an invalid input is provided during Project instantiation
152
+
153
+ def initialize(type)
154
+ super("Provided #{type} is in an invalid format.")
155
+ end
156
+ end
157
+
158
+ class InvalidNotificationType < Error
159
+ # Raised when an invalid notification type is provided
160
+
161
+ def initialize(msg = 'Provided notification type is invalid.')
162
+ super
163
+ end
164
+ end
165
+
166
+ class InvalidInputsError < Error
167
+ # Raised when an invalid inputs are provided during Project instantiation
168
+ end
169
+
170
+ class InvalidProjectConfigError < Error
171
+ # Raised when a public method fails due to an invalid datafile
172
+
173
+ def initialize(aborted_method)
174
+ super("Optimizely instance is not valid. Failing '#{aborted_method}'.")
175
+ end
176
+ end
177
+
178
+ class InvalidAttributeType < Error
179
+ # Raised when an attribute is not provided in expected type.
180
+
181
+ def initialize(msg = 'Provided attribute value is not in the expected data type.')
182
+ super
183
+ end
184
+ end
185
+
186
+ class InvalidSemanticVersion < Error
187
+ # Raised when an invalid value is provided as semantic version.
188
+
189
+ def initialize(msg = 'Provided semantic version is invalid.')
190
+ super
191
+ end
192
+ end
193
+ end