optimizely-sdk 3.9.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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 -508
  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 -321
  10. data/lib/optimizely/config_manager/project_config_manager.rb +24 -24
  11. data/lib/optimizely/config_manager/static_project_config_manager.rb +53 -47
  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 -500
  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 -107
  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 -1117
  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