optimizely-sdk 4.0.1 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/lib/optimizely/audience.rb +7 -7
- data/lib/optimizely/bucketer.rb +2 -2
- data/lib/optimizely/config/datafile_project_config.rb +58 -39
- data/lib/optimizely/config_manager/http_project_config_manager.rb +20 -10
- data/lib/optimizely/config_manager/project_config_manager.rb +2 -1
- data/lib/optimizely/config_manager/static_project_config_manager.rb +5 -3
- data/lib/optimizely/event/event_factory.rb +2 -2
- data/lib/optimizely/event_builder.rb +13 -13
- data/lib/optimizely/event_dispatcher.rb +2 -4
- data/lib/optimizely/exceptions.rb +69 -11
- data/lib/optimizely/helpers/constants.rb +45 -1
- data/lib/optimizely/helpers/http_utils.rb +3 -0
- data/lib/optimizely/helpers/sdk_settings.rb +61 -0
- data/lib/optimizely/helpers/validator.rb +54 -1
- data/lib/optimizely/notification_center_registry.rb +71 -0
- data/lib/optimizely/odp/lru_cache.rb +114 -0
- data/lib/optimizely/odp/odp_config.rb +102 -0
- data/lib/optimizely/odp/odp_event.rb +75 -0
- data/lib/optimizely/odp/odp_event_api_manager.rb +70 -0
- data/lib/optimizely/odp/odp_event_manager.rb +286 -0
- data/lib/optimizely/odp/odp_manager.rb +159 -0
- data/lib/optimizely/odp/odp_segment_api_manager.rb +122 -0
- data/lib/optimizely/odp/odp_segment_manager.rb +97 -0
- data/lib/optimizely/optimizely_config.rb +4 -2
- data/lib/optimizely/optimizely_factory.rb +17 -14
- data/lib/optimizely/optimizely_user_context.rb +40 -6
- data/lib/optimizely/user_condition_evaluator.rb +1 -1
- data/lib/optimizely/version.rb +2 -2
- data/lib/optimizely.rb +155 -23
- metadata +15 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7249ff9bec6f12c00a9a873df03e6f91c9692bcbe2388e87ea9a6a6f1472fbf5
|
4
|
+
data.tar.gz: 902fa025d32f1224833fa25f13158817ff3129244819a170ee3d907812290709
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b96a27927fd78a3d789b9edbb2c8488ba499c4f00220f08f9d9463691f38580db04f5dc6f7278873301a6c7217c54a9cf4f38d400b9feba196b7df70ec173e33
|
7
|
+
data.tar.gz: 368c9b5f096c8773c4bac487b8d6198ade424dde1ea6295449eaee3ecf5c0b4f7e2ab6b88a8bac4ab5ed2a2dce31f3ca24ef8c8596faae34cdae18aebfcdab79
|
data/LICENSE
CHANGED
@@ -187,7 +187,7 @@
|
|
187
187
|
same "printed page" as the copyright notice for easier
|
188
188
|
identification within third-party archives.
|
189
189
|
|
190
|
-
|
190
|
+
© Optimizely 2016
|
191
191
|
|
192
192
|
Licensed under the Apache License, Version 2.0 (the "License");
|
193
193
|
you may not use this file except in compliance with the License.
|
data/lib/optimizely/audience.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2016-2017, 2019-2020, Optimizely and contributors
|
4
|
+
# Copyright 2016-2017, 2019-2020, 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.
|
@@ -59,7 +59,7 @@ module Optimizely
|
|
59
59
|
user_condition_evaluator = UserConditionEvaluator.new(user_context, logger)
|
60
60
|
|
61
61
|
evaluate_user_conditions = lambda do |condition|
|
62
|
-
|
62
|
+
user_condition_evaluator.evaluate(condition)
|
63
63
|
end
|
64
64
|
|
65
65
|
evaluate_audience = lambda do |audience_id|
|
@@ -112,12 +112,12 @@ module Optimizely
|
|
112
112
|
# Returns array of segment names.
|
113
113
|
segments = []
|
114
114
|
|
115
|
-
conditions
|
116
|
-
|
117
|
-
|
115
|
+
case conditions
|
116
|
+
when Hash
|
117
|
+
segments.push(conditions['value']) if conditions.fetch('match', nil) == 'qualified'
|
118
|
+
when Array
|
119
|
+
conditions.each do |condition|
|
118
120
|
segments.concat @parse_segments.call(condition)
|
119
|
-
when Hash
|
120
|
-
segments.push(condition['value']) if condition.fetch('match', nil) == 'qualified'
|
121
121
|
end
|
122
122
|
end
|
123
123
|
|
data/lib/optimizely/bucketer.rb
CHANGED
@@ -110,8 +110,8 @@ module Optimizely
|
|
110
110
|
# parent_id - String entity ID to use for bucketing ID
|
111
111
|
# traffic_allocations - Array of traffic allocations
|
112
112
|
#
|
113
|
-
# Returns
|
114
|
-
# or nil if no match is found. The second value contains the array of reasons stating how the
|
113
|
+
# Returns an array of two values where first value is the entity ID corresponding to the provided bucket value
|
114
|
+
# or nil if no match is found. The second value contains the array of reasons stating how the decision was taken
|
115
115
|
decide_reasons = []
|
116
116
|
bucketing_key = format(BUCKETING_ID_TEMPLATE, bucketing_id: bucketing_id, entity_id: parent_id)
|
117
117
|
bucket_value = generate_bucket_value(bucketing_key)
|
@@ -93,7 +93,7 @@ module Optimizely
|
|
93
93
|
@experiment_key_map = generate_key_map(@experiments, 'key')
|
94
94
|
@experiment_id_map = generate_key_map(@experiments, 'id')
|
95
95
|
@audience_id_map = generate_key_map(@audiences, 'id')
|
96
|
-
@integration_key_map = generate_key_map(@integrations, 'key')
|
96
|
+
@integration_key_map = generate_key_map(@integrations, 'key', first_value: true)
|
97
97
|
@audience_id_map = @audience_id_map.merge(generate_key_map(@typed_audiences, 'id')) unless @typed_audiences.empty?
|
98
98
|
@variation_id_map = {}
|
99
99
|
@variation_key_map = {}
|
@@ -184,20 +184,19 @@ module Optimizely
|
|
184
184
|
# skip_json_validation - Optional boolean param which allows skipping JSON schema
|
185
185
|
# validation upon object invocation. By default JSON schema validation will be performed.
|
186
186
|
# Returns instance of DatafileProjectConfig, nil otherwise.
|
187
|
+
logger ||= SimpleLogger.new
|
187
188
|
if !skip_json_validation && !Helpers::Validator.datafile_valid?(datafile)
|
188
|
-
|
189
|
-
default_logger.log(Logger::ERROR, InvalidInputError.new('datafile').message)
|
189
|
+
logger.log(Logger::ERROR, InvalidInputError.new('datafile').message)
|
190
190
|
return nil
|
191
191
|
end
|
192
192
|
|
193
193
|
begin
|
194
194
|
config = new(datafile, logger, error_handler)
|
195
195
|
rescue StandardError => e
|
196
|
-
default_logger = SimpleLogger.new
|
197
196
|
error_to_handle = e.instance_of?(InvalidDatafileVersionError) ? e : InvalidInputError.new('datafile')
|
198
197
|
error_msg = error_to_handle.message
|
199
198
|
|
200
|
-
|
199
|
+
logger.log(Logger::ERROR, error_msg)
|
201
200
|
error_handler.handle_error error_to_handle
|
202
201
|
return nil
|
203
202
|
end
|
@@ -224,8 +223,9 @@ module Optimizely
|
|
224
223
|
experiment = @experiment_key_map[experiment_key]
|
225
224
|
return experiment if experiment
|
226
225
|
|
227
|
-
|
228
|
-
@
|
226
|
+
invalid_experiment_error = InvalidExperimentError.new(experiment_key: experiment_key)
|
227
|
+
@logger.log Logger::ERROR, invalid_experiment_error.message
|
228
|
+
@error_handler.handle_error invalid_experiment_error
|
229
229
|
nil
|
230
230
|
end
|
231
231
|
|
@@ -239,8 +239,9 @@ module Optimizely
|
|
239
239
|
experiment = @experiment_id_map[experiment_id]
|
240
240
|
return experiment if experiment
|
241
241
|
|
242
|
-
|
243
|
-
@
|
242
|
+
invalid_experiment_error = InvalidExperimentError.new(experiment_id: experiment_id)
|
243
|
+
@logger.log Logger::ERROR, invalid_experiment_error.message
|
244
|
+
@error_handler.handle_error invalid_experiment_error
|
244
245
|
nil
|
245
246
|
end
|
246
247
|
|
@@ -254,8 +255,9 @@ module Optimizely
|
|
254
255
|
experiment = @experiment_id_map[experiment_id]
|
255
256
|
return experiment['key'] unless experiment.nil?
|
256
257
|
|
257
|
-
|
258
|
-
@
|
258
|
+
invalid_experiment_error = InvalidExperimentError.new(experiment_id: experiment_id)
|
259
|
+
@logger.log Logger::ERROR, invalid_experiment_error.message
|
260
|
+
@error_handler.handle_error invalid_experiment_error
|
259
261
|
nil
|
260
262
|
end
|
261
263
|
|
@@ -269,8 +271,9 @@ module Optimizely
|
|
269
271
|
event = @event_key_map[event_key]
|
270
272
|
return event if event
|
271
273
|
|
272
|
-
|
273
|
-
@
|
274
|
+
invalid_event_error = InvalidEventError.new(event_key)
|
275
|
+
@logger.log Logger::ERROR, invalid_event_error.message
|
276
|
+
@error_handler.handle_error invalid_event_error
|
274
277
|
nil
|
275
278
|
end
|
276
279
|
|
@@ -284,8 +287,9 @@ module Optimizely
|
|
284
287
|
audience = @audience_id_map[audience_id]
|
285
288
|
return audience if audience
|
286
289
|
|
287
|
-
|
288
|
-
@
|
290
|
+
invalid_audience_error = InvalidAudienceError.new(audience_id)
|
291
|
+
@logger.log Logger::ERROR, invalid_audience_error.message
|
292
|
+
@error_handler.handle_error invalid_audience_error
|
289
293
|
nil
|
290
294
|
end
|
291
295
|
|
@@ -309,13 +313,15 @@ module Optimizely
|
|
309
313
|
variation = variation_id_map[variation_id]
|
310
314
|
return variation if variation
|
311
315
|
|
312
|
-
|
313
|
-
@
|
316
|
+
invalid_variation_error = InvalidVariationError.new(variation_id: variation_id)
|
317
|
+
@logger.log Logger::ERROR, invalid_variation_error.message
|
318
|
+
@error_handler.handle_error invalid_variation_error
|
314
319
|
return nil
|
315
320
|
end
|
316
321
|
|
317
|
-
|
318
|
-
@
|
322
|
+
invalid_experiment_error = InvalidExperimentError.new(experiment_key: experiment_key)
|
323
|
+
@logger.log Logger::ERROR, invalid_experiment_error.message
|
324
|
+
@error_handler.handle_error invalid_experiment_error
|
319
325
|
nil
|
320
326
|
end
|
321
327
|
|
@@ -332,13 +338,15 @@ module Optimizely
|
|
332
338
|
variation = variation_id_map_by_experiment_id[variation_id]
|
333
339
|
return variation if variation
|
334
340
|
|
335
|
-
|
336
|
-
@
|
341
|
+
invalid_variation_error = InvalidVariationError.new(variation_id: variation_id)
|
342
|
+
@logger.log Logger::ERROR, invalid_variation_error.message
|
343
|
+
@error_handler.handle_error invalid_variation_error
|
337
344
|
return nil
|
338
345
|
end
|
339
346
|
|
340
|
-
|
341
|
-
@
|
347
|
+
invalid_experiment_error = InvalidExperimentError.new(experiment_id: experiment_id)
|
348
|
+
@logger.log Logger::ERROR, invalid_experiment_error.message
|
349
|
+
@error_handler.handle_error invalid_experiment_error
|
342
350
|
nil
|
343
351
|
end
|
344
352
|
|
@@ -355,13 +363,15 @@ module Optimizely
|
|
355
363
|
variation = variation_key_map[variation_key]
|
356
364
|
return variation['id'] if variation
|
357
365
|
|
358
|
-
|
359
|
-
@
|
366
|
+
invalid_variation_error = InvalidVariationError.new(variation_key: variation_key)
|
367
|
+
@logger.log Logger::ERROR, invalid_variation_error.message
|
368
|
+
@error_handler.handle_error invalid_variation_error
|
360
369
|
return nil
|
361
370
|
end
|
362
371
|
|
363
|
-
|
364
|
-
@
|
372
|
+
invalid_experiment_error = InvalidExperimentError.new(experiment_id: experiment_id)
|
373
|
+
@logger.log Logger::ERROR, invalid_experiment_error.message
|
374
|
+
@error_handler.handle_error invalid_experiment_error
|
365
375
|
nil
|
366
376
|
end
|
367
377
|
|
@@ -378,13 +388,15 @@ module Optimizely
|
|
378
388
|
variation = variation_key_map[variation_key]
|
379
389
|
return variation['id'] if variation
|
380
390
|
|
381
|
-
|
382
|
-
@
|
391
|
+
invalid_variation_error = InvalidVariationError.new(variation_key: variation_key)
|
392
|
+
@logger.log Logger::ERROR, invalid_variation_error.message
|
393
|
+
@error_handler.handle_error invalid_variation_error
|
383
394
|
return nil
|
384
395
|
end
|
385
396
|
|
386
|
-
|
387
|
-
@
|
397
|
+
invalid_experiment_error = InvalidExperimentError.new(experiment_key: experiment_key)
|
398
|
+
@logger.log Logger::ERROR, invalid_experiment_error.message
|
399
|
+
@error_handler.handle_error invalid_experiment_error
|
388
400
|
nil
|
389
401
|
end
|
390
402
|
|
@@ -398,8 +410,9 @@ module Optimizely
|
|
398
410
|
experiment = @experiment_id_map[experiment_id]
|
399
411
|
return experiment['forcedVariations'] if experiment
|
400
412
|
|
401
|
-
|
402
|
-
@
|
413
|
+
invalid_experiment_error = InvalidExperimentError.new(experiment_id: experiment_id)
|
414
|
+
@logger.log Logger::ERROR, invalid_experiment_error.message
|
415
|
+
@error_handler.handle_error invalid_experiment_error
|
403
416
|
end
|
404
417
|
|
405
418
|
def get_attribute_id(attribute_key)
|
@@ -421,8 +434,9 @@ module Optimizely
|
|
421
434
|
end
|
422
435
|
return attribute_key if has_reserved_prefix
|
423
436
|
|
424
|
-
|
425
|
-
@
|
437
|
+
invalid_attribute_error = InvalidAttributeError.new(attribute_key)
|
438
|
+
@logger.log Logger::ERROR, invalid_attribute_error.message
|
439
|
+
@error_handler.handle_error invalid_attribute_error
|
426
440
|
nil
|
427
441
|
end
|
428
442
|
|
@@ -440,8 +454,9 @@ module Optimizely
|
|
440
454
|
variation = variation_id_map[variation_id]
|
441
455
|
return true if variation
|
442
456
|
|
443
|
-
|
444
|
-
@
|
457
|
+
invalid_variation_error = InvalidVariationError.new(variation_id: variation_id)
|
458
|
+
@logger.log Logger::ERROR, invalid_variation_error.message
|
459
|
+
@error_handler.handle_error invalid_variation_error
|
445
460
|
end
|
446
461
|
|
447
462
|
false
|
@@ -525,15 +540,19 @@ module Optimizely
|
|
525
540
|
flag_variation_map
|
526
541
|
end
|
527
542
|
|
528
|
-
def generate_key_map(array, key)
|
543
|
+
def generate_key_map(array, key, first_value: false)
|
529
544
|
# Helper method to generate map from key to hash in array of hashes
|
530
545
|
#
|
531
546
|
# array - Array consisting of hash
|
532
547
|
# key - Key in each hash which will be key in the map
|
548
|
+
# first_value - Determines which value to save if there are duplicate keys. By default the last instance of the key
|
549
|
+
# will be saved. Set to true to save the first key/value encountered.
|
533
550
|
#
|
534
551
|
# Returns map mapping key to hash
|
535
552
|
|
536
|
-
|
553
|
+
array
|
554
|
+
.group_by { |obj| obj[key] }
|
555
|
+
.transform_values { |group| first_value ? group.first : group.last }
|
537
556
|
end
|
538
557
|
end
|
539
558
|
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.
|
@@ -33,12 +33,12 @@ module Optimizely
|
|
33
33
|
class HTTPProjectConfigManager < ProjectConfigManager
|
34
34
|
# Config manager that polls for the datafile and updated ProjectConfig based on an update interval.
|
35
35
|
|
36
|
-
attr_reader :stopped
|
36
|
+
attr_reader :stopped, :sdk_key
|
37
37
|
|
38
38
|
# Initialize config manager. One of sdk_key or url has to be set to be able to use.
|
39
39
|
#
|
40
|
-
# sdk_key - Optional string uniquely identifying the datafile. It's required unless a
|
41
|
-
# datafile
|
40
|
+
# sdk_key - Optional string uniquely identifying the datafile. It's required unless a datafile with sdk_key is passed in.
|
41
|
+
# datafile - Optional JSON string representing the project. If nil, sdk_key is required.
|
42
42
|
# polling_interval - Optional floating point number representing time interval in seconds
|
43
43
|
# at which to request datafile and set ProjectConfig.
|
44
44
|
# blocking_timeout - Optional Time in seconds to block the config call until config object has been initialized.
|
@@ -83,6 +83,10 @@ module Optimizely
|
|
83
83
|
@notification_center = notification_center.is_a?(Optimizely::NotificationCenter) ? notification_center : NotificationCenter.new(@logger, @error_handler)
|
84
84
|
@optimizely_config = nil
|
85
85
|
@config = datafile.nil? ? nil : DatafileProjectConfig.create(datafile, @logger, @error_handler, @skip_json_validation)
|
86
|
+
@sdk_key = sdk_key || @config&.sdk_key
|
87
|
+
|
88
|
+
raise MissingSdkKeyError if @sdk_key.nil?
|
89
|
+
|
86
90
|
@mutex = Mutex.new
|
87
91
|
@resource = ConditionVariable.new
|
88
92
|
@async_scheduler = AsyncScheduler.new(method(:fetch_datafile_config), @polling_interval, auto_update, @logger)
|
@@ -98,11 +102,6 @@ module Optimizely
|
|
98
102
|
end
|
99
103
|
|
100
104
|
def start!
|
101
|
-
if @stopped
|
102
|
-
@logger.log(Logger::WARN, 'Not starting. Already stopped.')
|
103
|
-
return
|
104
|
-
end
|
105
|
-
|
106
105
|
@async_scheduler.start!
|
107
106
|
@stopped = false
|
108
107
|
end
|
@@ -142,7 +141,7 @@ module Optimizely
|
|
142
141
|
end
|
143
142
|
|
144
143
|
def optimizely_config
|
145
|
-
@optimizely_config = OptimizelyConfig.new(@config).config if @optimizely_config.nil?
|
144
|
+
@optimizely_config = OptimizelyConfig.new(@config, @logger).config if @optimizely_config.nil?
|
146
145
|
|
147
146
|
@optimizely_config
|
148
147
|
end
|
@@ -222,6 +221,10 @@ module Optimizely
|
|
222
221
|
|
223
222
|
@notification_center.send_notifications(NotificationCenter::NOTIFICATION_TYPES[:OPTIMIZELY_CONFIG_UPDATE])
|
224
223
|
|
224
|
+
NotificationCenterRegistry
|
225
|
+
.get_notification_center(@sdk_key, @logger)
|
226
|
+
&.send_notifications(NotificationCenter::NOTIFICATION_TYPES[:OPTIMIZELY_CONFIG_UPDATE])
|
227
|
+
|
225
228
|
@logger.log(Logger::DEBUG, 'Received new datafile and updated config. ' \
|
226
229
|
"Old revision number: #{previous_revision}. New revision number: #{@config.revision}.")
|
227
230
|
end
|
@@ -260,6 +263,13 @@ module Optimizely
|
|
260
263
|
return
|
261
264
|
end
|
262
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
|
+
|
263
273
|
@polling_interval = polling_interval
|
264
274
|
end
|
265
275
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2019, Optimizely and contributors
|
4
|
+
# Copyright 2019, 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.
|
@@ -20,5 +20,6 @@ module Optimizely
|
|
20
20
|
# Interface for fetching ProjectConfig instance.
|
21
21
|
|
22
22
|
def config; end
|
23
|
+
def sdk_key; end
|
23
24
|
end
|
24
25
|
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.
|
@@ -23,7 +23,7 @@ require_relative 'project_config_manager'
|
|
23
23
|
module Optimizely
|
24
24
|
class StaticProjectConfigManager < ProjectConfigManager
|
25
25
|
# Implementation of ProjectConfigManager interface.
|
26
|
-
attr_reader :config
|
26
|
+
attr_reader :config, :sdk_key
|
27
27
|
|
28
28
|
def initialize(datafile, logger, error_handler, skip_json_validation)
|
29
29
|
# Looks up and sets datafile and config based on response body.
|
@@ -41,11 +41,13 @@ module Optimizely
|
|
41
41
|
error_handler,
|
42
42
|
skip_json_validation
|
43
43
|
)
|
44
|
+
@logger = logger
|
45
|
+
@sdk_key = @config&.sdk_key
|
44
46
|
@optimizely_config = nil
|
45
47
|
end
|
46
48
|
|
47
49
|
def optimizely_config
|
48
|
-
@optimizely_config = OptimizelyConfig.new(@config).config if @optimizely_config.nil?
|
50
|
+
@optimizely_config = OptimizelyConfig.new(@config, @logger).config if @optimizely_config.nil?
|
49
51
|
|
50
52
|
@optimizely_config
|
51
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&.
|
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&.
|
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
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
|
@@ -17,6 +17,7 @@
|
|
17
17
|
#
|
18
18
|
require_relative 'exceptions'
|
19
19
|
require_relative 'helpers/http_utils'
|
20
|
+
require_relative 'helpers/constants'
|
20
21
|
|
21
22
|
module Optimizely
|
22
23
|
class NoOpEventDispatcher
|
@@ -26,9 +27,6 @@ module Optimizely
|
|
26
27
|
end
|
27
28
|
|
28
29
|
class EventDispatcher
|
29
|
-
# @api constants
|
30
|
-
REQUEST_TIMEOUT = 10
|
31
|
-
|
32
30
|
def initialize(logger: nil, error_handler: nil, proxy_config: nil)
|
33
31
|
@logger = logger || NoOpLogger.new
|
34
32
|
@error_handler = error_handler || NoOpErrorHandler.new
|
@@ -40,7 +38,7 @@ module Optimizely
|
|
40
38
|
# @param event - Event object
|
41
39
|
def dispatch_event(event)
|
42
40
|
response = Helpers::HttpUtils.make_request(
|
43
|
-
event.url, event.http_verb, event.params.to_json, event.headers, REQUEST_TIMEOUT, @proxy_config
|
41
|
+
event.url, event.http_verb, event.params.to_json, event.headers, Helpers::Constants::EVENT_DISPATCH_CONFIG[:REQUEST_TIMEOUT], @proxy_config
|
44
42
|
)
|
45
43
|
|
46
44
|
error_msg = "Event failed to dispatch with response code: #{response.code}"
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
#
|
4
|
-
# Copyright 2016-2020, 2022, Optimizely and contributors
|
4
|
+
# Copyright 2016-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.
|
@@ -25,19 +25,45 @@ module Optimizely
|
|
25
25
|
end
|
26
26
|
end
|
27
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
|
+
|
28
42
|
class InvalidAudienceError < Error
|
29
43
|
# Raised when an invalid audience is provided
|
30
44
|
|
31
|
-
|
32
|
-
|
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
|
33
53
|
end
|
34
54
|
end
|
35
55
|
|
36
56
|
class InvalidAttributeError < Error
|
37
57
|
# Raised when an invalid attribute is provided
|
38
58
|
|
39
|
-
|
40
|
-
|
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
|
41
67
|
end
|
42
68
|
end
|
43
69
|
|
@@ -60,24 +86,56 @@ module Optimizely
|
|
60
86
|
class InvalidExperimentError < Error
|
61
87
|
# Raised when an invalid experiment key is provided
|
62
88
|
|
63
|
-
|
64
|
-
|
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.")
|
65
104
|
end
|
66
105
|
end
|
67
106
|
|
68
107
|
class InvalidEventError < Error
|
69
108
|
# Raised when an invalid event key is provided
|
70
109
|
|
71
|
-
|
72
|
-
|
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
|
73
118
|
end
|
74
119
|
end
|
75
120
|
|
76
121
|
class InvalidVariationError < Error
|
77
122
|
# Raised when an invalid variation key or ID is provided
|
78
123
|
|
79
|
-
|
80
|
-
|
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.")
|
81
139
|
end
|
82
140
|
end
|
83
141
|
|