optimizely-sdk 5.0.0.pre.beta → 5.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.
@@ -102,11 +102,6 @@ module Optimizely
102
102
  end
103
103
 
104
104
  def start!
105
- if @stopped
106
- @logger.log(Logger::WARN, 'Not starting. Already stopped.')
107
- return
108
- end
109
-
110
105
  @async_scheduler.start!
111
106
  @stopped = false
112
107
  end
@@ -146,7 +141,7 @@ module Optimizely
146
141
  end
147
142
 
148
143
  def optimizely_config
149
- @optimizely_config = OptimizelyConfig.new(@config).config if @optimizely_config.nil?
144
+ @optimizely_config = OptimizelyConfig.new(@config, @logger).config if @optimizely_config.nil?
150
145
 
151
146
  @optimizely_config
152
147
  end
@@ -268,6 +263,13 @@ module Optimizely
268
263
  return
269
264
  end
270
265
 
266
+ if polling_interval < 30
267
+ @logger.log(
268
+ Logger::WARN,
269
+ 'Polling intervals below 30 seconds are not recommended.'
270
+ )
271
+ end
272
+
271
273
  @polling_interval = polling_interval
272
274
  end
273
275
 
@@ -41,12 +41,13 @@ module Optimizely
41
41
  error_handler,
42
42
  skip_json_validation
43
43
  )
44
+ @logger = logger
44
45
  @sdk_key = @config&.sdk_key
45
46
  @optimizely_config = nil
46
47
  end
47
48
 
48
49
  def optimizely_config
49
- @optimizely_config = OptimizelyConfig.new(@config).config if @optimizely_config.nil?
50
+ @optimizely_config = OptimizelyConfig.new(@config, @logger).config if @optimizely_config.nil?
50
51
 
51
52
  @optimizely_config
52
53
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #
4
- # Copyright 2019-2020, 2022, Optimizely and contributors
4
+ # Copyright 2019-2020, 2022-2023, Optimizely and contributors
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -72,7 +72,7 @@ module Optimizely
72
72
 
73
73
  def build_attribute_list(user_attributes, project_config)
74
74
  visitor_attributes = []
75
- user_attributes&.keys&.each do |attribute_key|
75
+ user_attributes&.each_key do |attribute_key|
76
76
  # Omit attribute values that are not supported by the log endpoint.
77
77
  attribute_value = user_attributes[attribute_key]
78
78
  next unless Helpers::Validator.attribute_valid?(attribute_key, attribute_value)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #
4
- # Copyright 2016-2019, 2022, Optimizely and contributors
4
+ # Copyright 2016-2019, 2022-2023, Optimizely and contributors
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -62,20 +62,20 @@ module Optimizely
62
62
 
63
63
  visitor_attributes = []
64
64
 
65
- attributes&.keys&.each do |attribute_key|
65
+ attributes&.each_key do |attribute_key|
66
66
  # Omit attribute values that are not supported by the log endpoint.
67
67
  attribute_value = attributes[attribute_key]
68
- if Helpers::Validator.attribute_valid?(attribute_key, attribute_value)
69
- attribute_id = project_config.get_attribute_id attribute_key
70
- if attribute_id
71
- visitor_attributes.push(
72
- entity_id: attribute_id,
73
- key: attribute_key,
74
- type: CUSTOM_ATTRIBUTE_FEATURE_TYPE,
75
- value: attribute_value
76
- )
77
- end
78
- end
68
+ next unless Helpers::Validator.attribute_valid?(attribute_key, attribute_value)
69
+
70
+ attribute_id = project_config.get_attribute_id attribute_key
71
+ next unless attribute_id
72
+
73
+ visitor_attributes.push(
74
+ entity_id: attribute_id,
75
+ key: attribute_key,
76
+ type: CUSTOM_ATTRIBUTE_FEATURE_TYPE,
77
+ value: attribute_value
78
+ )
79
79
  end
80
80
  # Append Bot Filtering Attribute
81
81
  if project_config.bot_filtering == true || project_config.bot_filtering == false
@@ -42,16 +42,28 @@ module Optimizely
42
42
  class InvalidAudienceError < Error
43
43
  # Raised when an invalid audience is provided
44
44
 
45
- def initialize(msg = 'Provided audience is not in datafile.')
46
- super
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
47
53
  end
48
54
  end
49
55
 
50
56
  class InvalidAttributeError < Error
51
57
  # Raised when an invalid attribute is provided
52
58
 
53
- def initialize(msg = 'Provided attribute is not in datafile.')
54
- super
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
55
67
  end
56
68
  end
57
69
 
@@ -74,24 +86,56 @@ module Optimizely
74
86
  class InvalidExperimentError < Error
75
87
  # Raised when an invalid experiment key is provided
76
88
 
77
- def initialize(msg = 'Provided experiment is not in datafile.')
78
- super
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.")
79
104
  end
80
105
  end
81
106
 
82
107
  class InvalidEventError < Error
83
108
  # Raised when an invalid event key is provided
84
109
 
85
- def initialize(msg = 'Provided event is not in datafile.')
86
- super
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
87
118
  end
88
119
  end
89
120
 
90
121
  class InvalidVariationError < Error
91
122
  # Raised when an invalid variation key or ID is provided
92
123
 
93
- def initialize(msg = 'Provided variation is not in datafile.')
94
- super
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.")
95
139
  end
96
140
  end
97
141
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #
4
- # Copyright 2016-2019, 2022, Optimizely and contributors
4
+ # Copyright 2016-2019, 2022-2023, Optimizely and contributors
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -190,14 +190,13 @@ module Optimizely
190
190
  # segments_cache - custom cache to be validated.
191
191
  #
192
192
  # Returns boolean depending on whether cache has required methods.
193
- (
194
- segments_cache.respond_to?(:reset) &&
193
+
194
+ segments_cache.respond_to?(:reset) &&
195
195
  segments_cache.method(:reset)&.parameters&.empty? &&
196
196
  segments_cache.respond_to?(:lookup) &&
197
197
  segments_cache.method(:lookup)&.parameters&.length&.positive? &&
198
198
  segments_cache.respond_to?(:save) &&
199
199
  segments_cache.method(:save)&.parameters&.length&.positive?
200
- )
201
200
  end
202
201
 
203
202
  def segment_manager_valid?(segment_manager)
@@ -206,13 +205,12 @@ module Optimizely
206
205
  # segment_manager - custom manager to be validated.
207
206
  #
208
207
  # Returns boolean depending on whether manager has required methods.
209
- (
210
- segment_manager.respond_to?(:odp_config) &&
208
+
209
+ segment_manager.respond_to?(:odp_config) &&
211
210
  segment_manager.respond_to?(:reset) &&
212
211
  segment_manager.method(:reset)&.parameters&.empty? &&
213
212
  segment_manager.respond_to?(:fetch_qualified_segments) &&
214
213
  (segment_manager.method(:fetch_qualified_segments)&.parameters&.length || 0) >= 3
215
- )
216
214
  end
217
215
 
218
216
  def event_manager_valid?(event_manager)
@@ -19,8 +19,9 @@ module Optimizely
19
19
  require 'json'
20
20
  class OptimizelyConfig
21
21
  include Optimizely::ConditionTreeEvaluator
22
- def initialize(project_config)
22
+ def initialize(project_config, logger = nil)
23
23
  @project_config = project_config
24
+ @logger = logger || NoOpLogger.new
24
25
  @rollouts = @project_config.rollouts
25
26
  @audiences = []
26
27
  audience_id_lookup_dict = {}
@@ -91,6 +92,7 @@ module Optimizely
91
92
 
92
93
  def experiments_map
93
94
  experiments_id_map.values.reduce({}) do |experiments_key_map, experiment|
95
+ @logger.log(Logger::WARN, "Duplicate experiment keys found in datafile: #{experiment['key']}") if experiments_key_map.key? experiment['key']
94
96
  experiments_key_map.update(experiment['key'] => experiment)
95
97
  end
96
98
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  #
4
- # Copyright 2019, 2022, Optimizely and contributors
4
+ # Copyright 2019, 2022-2023, Optimizely and contributors
5
5
  #
6
6
  # Licensed under the Apache License, Version 2.0 (the "License");
7
7
  # you may not use this file except in compliance with the License.
@@ -103,7 +103,7 @@ module Optimizely
103
103
  )
104
104
 
105
105
  Optimizely::Project.new(
106
- datafile, nil, logger, error_handler, nil, nil, sdk_key, config_manager, notification_center
106
+ datafile: datafile, logger: logger, error_handler: error_handler, sdk_key: sdk_key, config_manager: config_manager, notification_center: notification_center
107
107
  )
108
108
  end
109
109
 
@@ -111,7 +111,7 @@ module Optimizely
111
111
  #
112
112
  # @param config_manager - Required ConfigManagerInterface Responds to 'config' method.
113
113
  def self.default_instance_with_config_manager(config_manager)
114
- Optimizely::Project.new(nil, nil, nil, nil, nil, nil, nil, config_manager)
114
+ Optimizely::Project.new(config_manager: config_manager)
115
115
  end
116
116
 
117
117
  # Returns a new optimizely instance.
@@ -167,19 +167,17 @@ module Optimizely
167
167
  )
168
168
 
169
169
  Optimizely::Project.new(
170
- datafile,
171
- event_dispatcher,
172
- logger,
173
- error_handler,
174
- skip_json_validation,
175
- user_profile_service,
176
- sdk_key,
177
- config_manager,
178
- notification_center,
179
- event_processor,
180
- [],
181
- {},
182
- settings
170
+ datafile: datafile,
171
+ event_dispatcher: event_dispatcher,
172
+ logger: logger,
173
+ error_handler: error_handler,
174
+ skip_json_validation: skip_json_validation,
175
+ user_profile_service: user_profile_service,
176
+ sdk_key: sdk_key,
177
+ config_manager: config_manager,
178
+ notification_center: notification_center,
179
+ event_processor: event_processor,
180
+ settings: settings
183
181
  )
184
182
  end
185
183
  end
@@ -17,5 +17,5 @@
17
17
  #
18
18
  module Optimizely
19
19
  CLIENT_ENGINE = 'ruby-sdk'
20
- VERSION = '5.0.0-beta'
20
+ VERSION = '5.0.0'
21
21
  end
data/lib/optimizely.rb CHANGED
@@ -70,20 +70,20 @@ module Optimizely
70
70
  # @param event_processor_options: Optional hash of options to be passed to the default batch event processor.
71
71
  # @param settings: Optional instance of OptimizelySdkSettings for sdk configuration.
72
72
 
73
- def initialize( # rubocop:disable Metrics/ParameterLists
74
- datafile = nil,
75
- event_dispatcher = nil,
76
- logger = nil,
77
- error_handler = nil,
78
- skip_json_validation = false, # rubocop:disable Style/OptionalBooleanParameter
79
- user_profile_service = nil,
80
- sdk_key = nil,
81
- config_manager = nil,
82
- notification_center = nil,
83
- event_processor = nil,
84
- default_decide_options = [],
85
- event_processor_options = {},
86
- settings = nil
73
+ def initialize(
74
+ datafile: nil,
75
+ event_dispatcher: nil,
76
+ logger: nil,
77
+ error_handler: nil,
78
+ skip_json_validation: false,
79
+ user_profile_service: nil,
80
+ sdk_key: nil,
81
+ config_manager: nil,
82
+ notification_center: nil,
83
+ event_processor: nil,
84
+ default_decide_options: [],
85
+ event_processor_options: {},
86
+ settings: nil
87
87
  )
88
88
  @logger = logger || NoOpLogger.new
89
89
  @error_handler = error_handler || NoOpErrorHandler.new
@@ -889,7 +889,7 @@ module Optimizely
889
889
  if @config_manager.respond_to?(:optimizely_config)
890
890
  @config_manager.optimizely_config
891
891
  else
892
- OptimizelyConfig.new(project_config).config
892
+ OptimizelyConfig.new(project_config, @logger).config
893
893
  end
894
894
  end
895
895
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: optimizely-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0.pre.beta
4
+ version: 5.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Optimizely
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-28 00:00:00.000000000 Z
11
+ date: 2024-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -98,14 +98,14 @@ dependencies:
98
98
  name: json-schema
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
103
  version: '2.6'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '2.6'
111
111
  - !ruby/object:Gem::Dependency
@@ -204,12 +204,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
204
204
  requirements:
205
205
  - - ">="
206
206
  - !ruby/object:Gem::Version
207
- version: '2.7'
207
+ version: '3.0'
208
208
  required_rubygems_version: !ruby/object:Gem::Requirement
209
209
  requirements:
210
- - - ">"
210
+ - - ">="
211
211
  - !ruby/object:Gem::Version
212
- version: 1.3.1
212
+ version: '0'
213
213
  requirements: []
214
214
  rubygems_version: 3.3.7
215
215
  signing_key: