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.
- checksums.yaml +4 -4
- data/LICENSE +202 -202
- data/lib/optimizely/audience.rb +127 -127
- data/lib/optimizely/bucketer.rb +156 -156
- data/lib/optimizely/condition_tree_evaluator.rb +123 -123
- data/lib/optimizely/config/datafile_project_config.rb +48 -32
- data/lib/optimizely/config/proxy_config.rb +34 -34
- data/lib/optimizely/config_manager/async_scheduler.rb +95 -95
- data/lib/optimizely/config_manager/http_project_config_manager.rb +340 -338
- data/lib/optimizely/config_manager/project_config_manager.rb +25 -25
- data/lib/optimizely/config_manager/static_project_config_manager.rb +55 -54
- data/lib/optimizely/decide/optimizely_decide_option.rb +28 -28
- data/lib/optimizely/decide/optimizely_decision.rb +60 -60
- data/lib/optimizely/decide/optimizely_decision_message.rb +26 -26
- data/lib/optimizely/decision_service.rb +563 -563
- data/lib/optimizely/error_handler.rb +39 -39
- data/lib/optimizely/event/batch_event_processor.rb +235 -235
- data/lib/optimizely/event/entity/conversion_event.rb +44 -44
- data/lib/optimizely/event/entity/decision.rb +38 -38
- data/lib/optimizely/event/entity/event_batch.rb +86 -86
- data/lib/optimizely/event/entity/event_context.rb +50 -50
- data/lib/optimizely/event/entity/impression_event.rb +48 -48
- data/lib/optimizely/event/entity/snapshot.rb +33 -33
- data/lib/optimizely/event/entity/snapshot_event.rb +48 -48
- data/lib/optimizely/event/entity/user_event.rb +22 -22
- data/lib/optimizely/event/entity/visitor.rb +36 -36
- data/lib/optimizely/event/entity/visitor_attribute.rb +38 -38
- data/lib/optimizely/event/event_factory.rb +156 -156
- data/lib/optimizely/event/event_processor.rb +25 -25
- data/lib/optimizely/event/forwarding_event_processor.rb +44 -44
- data/lib/optimizely/event/user_event_factory.rb +88 -88
- data/lib/optimizely/event_builder.rb +221 -221
- data/lib/optimizely/event_dispatcher.rb +69 -69
- data/lib/optimizely/exceptions.rb +193 -149
- data/lib/optimizely/helpers/constants.rb +459 -459
- data/lib/optimizely/helpers/date_time_utils.rb +30 -30
- data/lib/optimizely/helpers/event_tag_utils.rb +132 -132
- data/lib/optimizely/helpers/group.rb +31 -31
- data/lib/optimizely/helpers/http_utils.rb +68 -68
- data/lib/optimizely/helpers/sdk_settings.rb +61 -61
- data/lib/optimizely/helpers/validator.rb +236 -238
- data/lib/optimizely/helpers/variable_type.rb +67 -67
- data/lib/optimizely/logger.rb +46 -46
- data/lib/optimizely/notification_center.rb +174 -174
- data/lib/optimizely/notification_center_registry.rb +71 -71
- data/lib/optimizely/odp/lru_cache.rb +114 -114
- data/lib/optimizely/odp/odp_config.rb +102 -102
- data/lib/optimizely/odp/odp_event.rb +75 -75
- data/lib/optimizely/odp/odp_event_api_manager.rb +70 -70
- data/lib/optimizely/odp/odp_event_manager.rb +286 -286
- data/lib/optimizely/odp/odp_manager.rb +159 -159
- data/lib/optimizely/odp/odp_segment_api_manager.rb +122 -122
- data/lib/optimizely/odp/odp_segment_manager.rb +97 -97
- data/lib/optimizely/optimizely_config.rb +273 -271
- data/lib/optimizely/optimizely_factory.rb +184 -186
- data/lib/optimizely/optimizely_user_context.rb +238 -238
- data/lib/optimizely/params.rb +31 -31
- data/lib/optimizely/project_config.rb +99 -99
- data/lib/optimizely/semantic_version.rb +166 -166
- data/lib/optimizely/user_condition_evaluator.rb +391 -391
- data/lib/optimizely/user_profile_service.rb +35 -35
- data/lib/optimizely/version.rb +21 -21
- data/lib/optimizely.rb +1262 -1262
- 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
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
def initialize(
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
super
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
class
|
143
|
-
# Raised when an
|
144
|
-
|
145
|
-
def initialize(
|
146
|
-
super
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
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
|