optimizely-sdk 3.10.1 → 4.0.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 (54) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +202 -202
  3. data/lib/optimizely/audience.rb +127 -97
  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 +539 -552
  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 +330 -329
  10. data/lib/optimizely/config_manager/project_config_manager.rb +24 -24
  11. data/lib/optimizely/config_manager/static_project_config_manager.rb +53 -52
  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 -234
  18. data/lib/optimizely/event/entity/conversion_event.rb +44 -43
  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 -47
  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 -35
  27. data/lib/optimizely/event/entity/visitor_attribute.rb +38 -37
  28. data/lib/optimizely/event/event_factory.rb +156 -155
  29. data/lib/optimizely/event/event_processor.rb +25 -25
  30. data/lib/optimizely/event/forwarding_event_processor.rb +44 -43
  31. data/lib/optimizely/event/user_event_factory.rb +88 -88
  32. data/lib/optimizely/event_builder.rb +221 -228
  33. data/lib/optimizely/event_dispatcher.rb +71 -71
  34. data/lib/optimizely/exceptions.rb +135 -139
  35. data/lib/optimizely/helpers/constants.rb +415 -397
  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 +65 -64
  40. data/lib/optimizely/helpers/validator.rb +183 -183
  41. data/lib/optimizely/helpers/variable_type.rb +67 -67
  42. data/lib/optimizely/logger.rb +46 -45
  43. data/lib/optimizely/notification_center.rb +174 -176
  44. data/lib/optimizely/optimizely_config.rb +271 -272
  45. data/lib/optimizely/optimizely_factory.rb +181 -181
  46. data/lib/optimizely/optimizely_user_context.rb +204 -179
  47. data/lib/optimizely/params.rb +31 -31
  48. data/lib/optimizely/project_config.rb +99 -91
  49. data/lib/optimizely/semantic_version.rb +166 -166
  50. data/lib/optimizely/{custom_attribute_condition_evaluator.rb → user_condition_evaluator.rb} +391 -369
  51. data/lib/optimizely/user_profile_service.rb +35 -35
  52. data/lib/optimizely/version.rb +21 -21
  53. data/lib/optimizely.rb +1130 -1145
  54. metadata +13 -13
@@ -1,183 +1,183 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2016-2019, 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 'constants'
19
- require 'json'
20
- require 'json-schema'
21
-
22
- module Optimizely
23
- module Helpers
24
- module Validator
25
- module_function
26
-
27
- def attributes_valid?(attributes)
28
- # Determines if provided attributes are valid.
29
- #
30
- # attributes - User attributes to be validated.
31
- #
32
- # Returns boolean depending on validity of attributes.
33
-
34
- attributes.is_a?(Hash)
35
- end
36
-
37
- def attribute_valid?(attribute_key, attribute_value)
38
- # Determines if provided attribute_key and attribute_value are valid.
39
- #
40
- # attribute_key - Variable which needs to be validated.
41
- # attribute_value - Variable which needs to be validated.
42
- #
43
- # Returns boolean depending on validity of attribute_key and attribute_value.
44
-
45
- return false unless attribute_key.is_a?(String) || attribute_key.is_a?(Symbol)
46
-
47
- return true if (boolean? attribute_value) || (attribute_value.is_a? String)
48
-
49
- finite_number?(attribute_value)
50
- end
51
-
52
- def event_tags_valid?(event_tags)
53
- # Determines if provided event tags are valid.
54
- #
55
- # event_tags - Event tags to be validated.
56
- #
57
- # Returns boolean depending on validity of event tags.
58
-
59
- event_tags.is_a?(Hash)
60
- end
61
-
62
- def datafile_valid?(datafile)
63
- # Determines if a given datafile is valid.
64
- #
65
- # datafile - String JSON representing the project.
66
- #
67
- # Returns boolean depending on validity of datafile.
68
-
69
- begin
70
- datafile = JSON.parse(datafile)
71
- rescue
72
- return false
73
- end
74
-
75
- JSON::Validator.validate(Helpers::Constants::JSON_SCHEMA_V2, datafile)
76
- end
77
-
78
- def error_handler_valid?(error_handler)
79
- # Determines if a given error handler is valid.
80
- #
81
- # error_handler - error_handler to be validated.
82
- #
83
- # Returns boolean depending on whether error_handler has a handle_error method.
84
-
85
- error_handler.respond_to?(:handle_error)
86
- end
87
-
88
- def event_dispatcher_valid?(event_dispatcher)
89
- # Determines if a given event dispatcher is valid.
90
- #
91
- # event_dispatcher - event_dispatcher to be validated.
92
- #
93
- # Returns boolean depending on whether event_dispatcher has a dispatch_event method.
94
-
95
- event_dispatcher.respond_to?(:dispatch_event)
96
- end
97
-
98
- def logger_valid?(logger)
99
- # Determines if a given logger is valid.
100
- #
101
- # logger - logger to be validated.
102
- #
103
- # Returns boolean depending on whether logger has a log method.
104
-
105
- logger.respond_to?(:log)
106
- end
107
-
108
- def string_numeric?(str)
109
- !Float(str).nil?
110
- rescue
111
- false
112
- end
113
-
114
- def inputs_valid?(variables, logger = NoOpLogger.new, level = Logger::ERROR)
115
- # Determines if values of variables in given array are non empty string.
116
- #
117
- # variables - array values to validate.
118
- #
119
- # logger - logger.
120
- #
121
- # Returns boolean True if all of the values are valid, False otherwise.
122
-
123
- return false unless variables.respond_to?(:each) && !variables.empty?
124
-
125
- is_valid = true
126
- if variables.include? :user_id
127
- # Empty str is a valid user ID.
128
- unless variables[:user_id].is_a?(String)
129
- is_valid = false
130
- logger.log(level, "#{Constants::INPUT_VARIABLES['USER_ID']} is invalid")
131
- end
132
- variables.delete :user_id
133
- end
134
-
135
- if variables.include? :variable_type
136
- # Empty variable_type is a valid user ID.
137
- unless variables[:variable_type].is_a?(String) || !variables[:variable_type]
138
- is_valid = false
139
- logger.log(level, "#{Constants::INPUT_VARIABLES['VARIABLE_TYPE']} is invalid")
140
- end
141
- variables.delete :variable_type
142
- end
143
-
144
- variables.each do |key, value|
145
- next if value.is_a?(String) && !value.empty?
146
-
147
- is_valid = false
148
- next unless logger_valid?(logger) && level
149
-
150
- logger.log(level, "#{Constants::INPUT_VARIABLES[key.to_s.upcase]} is invalid")
151
- end
152
- is_valid
153
- end
154
-
155
- def boolean?(value)
156
- # Returns true if given value type is boolean.
157
- # false otherwise.
158
-
159
- value.is_a?(TrueClass) || value.is_a?(FalseClass)
160
- end
161
-
162
- def same_types?(value_1, value_2)
163
- # Returns true if given values are of same types.
164
- # false otherwise.
165
- # Numeric values are considered as same type.
166
-
167
- return true if value_1.is_a?(Numeric) && value_2.is_a?(Numeric)
168
-
169
- return true if boolean?(value_1) && boolean?(value_2)
170
-
171
- value_1.class == value_2.class
172
- end
173
-
174
- def finite_number?(value)
175
- # Returns true if the given value is a number, enforces
176
- # absolute limit of 2^53 and restricts NaN, Infinity, -Infinity.
177
- # false otherwise.
178
-
179
- value.is_a?(Numeric) && value.to_f.finite? && value.abs <= Constants::FINITE_NUMBER_LIMIT
180
- end
181
- end
182
- end
183
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2016-2019, 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 'constants'
19
+ require 'json'
20
+ require 'json-schema'
21
+
22
+ module Optimizely
23
+ module Helpers
24
+ module Validator
25
+ module_function
26
+
27
+ def attributes_valid?(attributes)
28
+ # Determines if provided attributes are valid.
29
+ #
30
+ # attributes - User attributes to be validated.
31
+ #
32
+ # Returns boolean depending on validity of attributes.
33
+
34
+ attributes.is_a?(Hash)
35
+ end
36
+
37
+ def attribute_valid?(attribute_key, attribute_value)
38
+ # Determines if provided attribute_key and attribute_value are valid.
39
+ #
40
+ # attribute_key - Variable which needs to be validated.
41
+ # attribute_value - Variable which needs to be validated.
42
+ #
43
+ # Returns boolean depending on validity of attribute_key and attribute_value.
44
+
45
+ return false unless attribute_key.is_a?(String) || attribute_key.is_a?(Symbol)
46
+
47
+ return true if (boolean? attribute_value) || (attribute_value.is_a? String)
48
+
49
+ finite_number?(attribute_value)
50
+ end
51
+
52
+ def event_tags_valid?(event_tags)
53
+ # Determines if provided event tags are valid.
54
+ #
55
+ # event_tags - Event tags to be validated.
56
+ #
57
+ # Returns boolean depending on validity of event tags.
58
+
59
+ event_tags.is_a?(Hash)
60
+ end
61
+
62
+ def datafile_valid?(datafile)
63
+ # Determines if a given datafile is valid.
64
+ #
65
+ # datafile - String JSON representing the project.
66
+ #
67
+ # Returns boolean depending on validity of datafile.
68
+
69
+ begin
70
+ datafile = JSON.parse(datafile)
71
+ rescue
72
+ return false
73
+ end
74
+
75
+ JSON::Validator.validate(Helpers::Constants::JSON_SCHEMA_V2, datafile)
76
+ end
77
+
78
+ def error_handler_valid?(error_handler)
79
+ # Determines if a given error handler is valid.
80
+ #
81
+ # error_handler - error_handler to be validated.
82
+ #
83
+ # Returns boolean depending on whether error_handler has a handle_error method.
84
+
85
+ error_handler.respond_to?(:handle_error)
86
+ end
87
+
88
+ def event_dispatcher_valid?(event_dispatcher)
89
+ # Determines if a given event dispatcher is valid.
90
+ #
91
+ # event_dispatcher - event_dispatcher to be validated.
92
+ #
93
+ # Returns boolean depending on whether event_dispatcher has a dispatch_event method.
94
+
95
+ event_dispatcher.respond_to?(:dispatch_event)
96
+ end
97
+
98
+ def logger_valid?(logger)
99
+ # Determines if a given logger is valid.
100
+ #
101
+ # logger - logger to be validated.
102
+ #
103
+ # Returns boolean depending on whether logger has a log method.
104
+
105
+ logger.respond_to?(:log)
106
+ end
107
+
108
+ def string_numeric?(str)
109
+ !Float(str).nil?
110
+ rescue
111
+ false
112
+ end
113
+
114
+ def inputs_valid?(variables, logger = NoOpLogger.new, level = Logger::ERROR)
115
+ # Determines if values of variables in given array are non empty string.
116
+ #
117
+ # variables - array values to validate.
118
+ #
119
+ # logger - logger.
120
+ #
121
+ # Returns boolean True if all of the values are valid, False otherwise.
122
+
123
+ return false unless variables.respond_to?(:each) && !variables.empty?
124
+
125
+ is_valid = true
126
+ if variables.include? :user_id
127
+ # Empty str is a valid user ID.
128
+ unless variables[:user_id].is_a?(String)
129
+ is_valid = false
130
+ logger.log(level, "#{Constants::INPUT_VARIABLES['USER_ID']} is invalid")
131
+ end
132
+ variables.delete :user_id
133
+ end
134
+
135
+ if variables.include? :variable_type
136
+ # Empty variable_type is a valid user ID.
137
+ unless variables[:variable_type].is_a?(String) || !variables[:variable_type]
138
+ is_valid = false
139
+ logger.log(level, "#{Constants::INPUT_VARIABLES['VARIABLE_TYPE']} is invalid")
140
+ end
141
+ variables.delete :variable_type
142
+ end
143
+
144
+ variables.each do |key, value|
145
+ next if value.is_a?(String) && !value.empty?
146
+
147
+ is_valid = false
148
+ next unless logger_valid?(logger) && level
149
+
150
+ logger.log(level, "#{Constants::INPUT_VARIABLES[key.to_s.upcase]} is invalid")
151
+ end
152
+ is_valid
153
+ end
154
+
155
+ def boolean?(value)
156
+ # Returns true if given value type is boolean.
157
+ # false otherwise.
158
+
159
+ value.is_a?(TrueClass) || value.is_a?(FalseClass)
160
+ end
161
+
162
+ def same_types?(value_1, value_2)
163
+ # Returns true if given values are of same types.
164
+ # false otherwise.
165
+ # Numeric values are considered as same type.
166
+
167
+ return true if value_1.is_a?(Numeric) && value_2.is_a?(Numeric)
168
+
169
+ return true if boolean?(value_1) && boolean?(value_2)
170
+
171
+ value_1.instance_of?(value_2.class)
172
+ end
173
+
174
+ def finite_number?(value)
175
+ # Returns true if the given value is a number, enforces
176
+ # absolute limit of 2^53 and restricts NaN, Infinity, -Infinity.
177
+ # false otherwise.
178
+
179
+ value.is_a?(Numeric) && value.to_f.finite? && value.abs <= Constants::FINITE_NUMBER_LIMIT
180
+ end
181
+ end
182
+ end
183
+ end
@@ -1,67 +1,67 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2017, 2020, 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 'optimizely/logger'
19
-
20
- module Optimizely
21
- module Helpers
22
- module VariableType
23
- module_function
24
-
25
- def cast_value_to_type(value, variable_type, logger)
26
- # Attempts to cast the given value to the specified type
27
- #
28
- # value - The string value to cast
29
- # variable_type - String variable type
30
- #
31
- # Returns the cast value or nil if not able to cast
32
- return_value = nil
33
-
34
- case variable_type
35
- when 'boolean'
36
- return_value = value == 'true'
37
- when 'double'
38
- begin
39
- return_value = Float(value)
40
- rescue => e
41
- logger.log(Logger::ERROR, "Unable to cast variable value '#{value}' to type "\
42
- "'#{variable_type}': #{e.message}.")
43
- end
44
- when 'integer'
45
- begin
46
- return_value = Integer(value)
47
- rescue => e
48
- logger.log(Logger::ERROR, "Unable to cast variable value '#{value}' to type "\
49
- "'#{variable_type}': #{e.message}.")
50
- end
51
- when 'json'
52
- begin
53
- return_value = JSON.parse(value)
54
- rescue => e
55
- logger.log(Logger::ERROR, "Unable to cast variable value '#{value}' to type "\
56
- "'#{variable_type}': #{e.message}.")
57
- end
58
- else
59
- # default case is string
60
- return_value = value
61
- end
62
-
63
- return_value
64
- end
65
- end
66
- end
67
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2017, 2020, 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 'optimizely/logger'
19
+
20
+ module Optimizely
21
+ module Helpers
22
+ module VariableType
23
+ module_function
24
+
25
+ def cast_value_to_type(value, variable_type, logger)
26
+ # Attempts to cast the given value to the specified type
27
+ #
28
+ # value - The string value to cast
29
+ # variable_type - String variable type
30
+ #
31
+ # Returns the cast value or nil if not able to cast
32
+ return_value = nil
33
+
34
+ case variable_type
35
+ when 'boolean'
36
+ return_value = value == 'true'
37
+ when 'double'
38
+ begin
39
+ return_value = Float(value)
40
+ rescue => e
41
+ logger.log(Logger::ERROR, "Unable to cast variable value '#{value}' to type "\
42
+ "'#{variable_type}': #{e.message}.")
43
+ end
44
+ when 'integer'
45
+ begin
46
+ return_value = Integer(value)
47
+ rescue => e
48
+ logger.log(Logger::ERROR, "Unable to cast variable value '#{value}' to type "\
49
+ "'#{variable_type}': #{e.message}.")
50
+ end
51
+ when 'json'
52
+ begin
53
+ return_value = JSON.parse(value)
54
+ rescue => e
55
+ logger.log(Logger::ERROR, "Unable to cast variable value '#{value}' to type "\
56
+ "'#{variable_type}': #{e.message}.")
57
+ end
58
+ else
59
+ # default case is string
60
+ return_value = value
61
+ end
62
+
63
+ return_value
64
+ end
65
+ end
66
+ end
67
+ end
@@ -1,45 +1,46 @@
1
- # frozen_string_literal: true
2
-
3
- #
4
- # Copyright 2016-2017, 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 'logger'
19
-
20
- module Optimizely
21
- class BaseLogger
22
- # Class encapsulating logging functionality. Override with your own logger providing log method.
23
-
24
- def log(_level, _message); end
25
- end
26
-
27
- class NoOpLogger < BaseLogger
28
- # Class providing log method which logs nothing.
29
-
30
- def log(_level, _message); end
31
- end
32
-
33
- class SimpleLogger < BaseLogger
34
- # Simple wrapper around Logger.
35
-
36
- def initialize(min_level = Logger::INFO)
37
- @logger = Logger.new(STDOUT)
38
- @logger.level = min_level
39
- end
40
-
41
- def log(level, message)
42
- @logger.add(level, message)
43
- end
44
- end
45
- end
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Copyright 2016-2017, 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 'logger'
19
+
20
+ module Optimizely
21
+ class BaseLogger
22
+ # Class encapsulating logging functionality. Override with your own logger providing log method.
23
+
24
+ def log(_level, _message); end
25
+ end
26
+
27
+ class NoOpLogger < BaseLogger
28
+ # Class providing log method which logs nothing.
29
+
30
+ def log(_level, _message); end
31
+ end
32
+
33
+ class SimpleLogger < BaseLogger
34
+ # Simple wrapper around Logger.
35
+
36
+ def initialize(min_level = Logger::INFO)
37
+ super()
38
+ @logger = Logger.new($stdout)
39
+ @logger.level = min_level
40
+ end
41
+
42
+ def log(level, message)
43
+ @logger.add(level, message)
44
+ end
45
+ end
46
+ end