optimizely-sdk 2.0.0.beta → 2.0.0.beta1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b6da10a1ad97624a7523adcdc6841b2999ab35d3
4
- data.tar.gz: 3865376c1962511db8d8350041fbc830b29b16c6
3
+ metadata.gz: f57d0b3e13c6c5bc057719cd5fa0689c9b93ade1
4
+ data.tar.gz: e67d075ed5fc5e42e41e8a5620e4e038ae3f1afd
5
5
  SHA512:
6
- metadata.gz: bf35c547babd0be1d576bf8926e23fa9e9292b47bf6a74df9a8cda19b00bd2a3da974c7a840dba7d6ac3aa3132b192caa692b727bc5bdfdf3a3a85c933ef58da
7
- data.tar.gz: b587d153eb46d6b779ebc298dfde188824f7c5f3fe1cc9c2b4e890878a9c190e9d9051baccbc8d18329670d81c5e5437e53f2d69d4c790a785b8fcb8fa2ac2e3
6
+ metadata.gz: 5fe41284c79ebc016276afcac83a1d87fb6e7a355738c8ff6c9fb38cd4c7d1a0494c44558394170edd380c0dee42c8accc91d67afb300a6d973a33f03762e984
7
+ data.tar.gz: 85fa4cb24da1cdd082846b80f4939419023c774e9305d048e9564381e68e4acdf78f76a937885998523afdecf47cce1c09dca3eb7b04ea320c852805d69b44cd
data/lib/optimizely.rb CHANGED
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
- # Copyright 2016-2017, Optimizely and contributors
4
+ # Copyright 2016-2018, Optimizely and contributors
3
5
  #
4
6
  # Licensed under the Apache License, Version 2.0 (the "License");
5
7
  # you may not use this file except in compliance with the License.
@@ -24,11 +26,11 @@ require_relative 'optimizely/helpers/group'
24
26
  require_relative 'optimizely/helpers/validator'
25
27
  require_relative 'optimizely/helpers/variable_type'
26
28
  require_relative 'optimizely/logger'
29
+ require_relative 'optimizely/notification_center'
27
30
  require_relative 'optimizely/project_config'
28
31
 
29
32
  module Optimizely
30
33
  class Project
31
-
32
34
  # Boolean representing if the instance represents a usable Optimizely Project
33
35
  attr_reader :is_valid
34
36
 
@@ -38,6 +40,7 @@ module Optimizely
38
40
  attr_reader :event_builder
39
41
  attr_reader :event_dispatcher
40
42
  attr_reader :logger
43
+ attr_reader :notification_center
41
44
 
42
45
  def initialize(datafile, event_dispatcher = nil, logger = nil, error_handler = nil, skip_json_validation = false, user_profile_service = nil)
43
46
  # Constructor for Projects.
@@ -82,7 +85,8 @@ module Optimizely
82
85
  end
83
86
 
84
87
  @decision_service = DecisionService.new(@config, @user_profile_service)
85
- @event_builder = EventBuilder.new(@config)
88
+ @event_builder = EventBuilder.new(@config, logger)
89
+ @notification_center = NotificationCenter.new(@logger, @error_handler)
86
90
  end
87
91
 
88
92
  def activate(experiment_key, user_id, attributes = nil)
@@ -131,6 +135,11 @@ module Optimizely
131
135
  return nil
132
136
  end
133
137
 
138
+ if user_id.to_s.empty?
139
+ @logger.log(Logger::ERROR, 'User ID cannot be empty.')
140
+ return nil
141
+ end
142
+
134
143
  unless user_inputs_valid?(attributes)
135
144
  @logger.log(Logger::INFO, "Not activating user '#{user_id}.")
136
145
  return nil
@@ -140,13 +149,39 @@ module Optimizely
140
149
 
141
150
  unless variation_id.nil?
142
151
  variation = @config.get_variation_from_id(experiment_key, variation_id)
143
- if variation
144
- return variation['key']
145
- end
152
+ return variation['key'] if variation
146
153
  end
147
154
  nil
148
155
  end
149
156
 
157
+ def set_forced_variation(experiment_key, user_id, variation_key)
158
+ # Force a user into a variation for a given experiment.
159
+ #
160
+ # experiment_key - String - key identifying the experiment.
161
+ # user_id - String - The user ID to be used for bucketing.
162
+ # variation_key - The variation key specifies the variation which the user will
163
+ # be forced into. If nil, then clear the existing experiment-to-variation mapping.
164
+ #
165
+ # Returns - Boolean - indicates if the set completed successfully.
166
+
167
+ @config.set_forced_variation(experiment_key, user_id, variation_key)
168
+ end
169
+
170
+ def get_forced_variation(experiment_key, user_id)
171
+ # Gets the forced variation for a given user and experiment.
172
+ #
173
+ # experiment_key - String - Key identifying the experiment.
174
+ # user_id - String - The user ID to be used for bucketing.
175
+ #
176
+ # Returns String|nil The forced variation key.
177
+
178
+ forced_variation_key = nil
179
+ forced_variation = @config.get_forced_variation(experiment_key, user_id)
180
+ forced_variation_key = forced_variation['key'] if forced_variation
181
+
182
+ forced_variation_key
183
+ end
184
+
150
185
  def track(event_key, user_id, attributes = nil, event_tags = nil)
151
186
  # Send conversion event to Optimizely.
152
187
  #
@@ -161,11 +196,9 @@ module Optimizely
161
196
  return nil
162
197
  end
163
198
 
164
- if event_tags and event_tags.is_a? Numeric
165
- event_tags = {
166
- 'revenue' => event_tags
167
- }
168
- @logger.log(Logger::WARN, 'Event value is deprecated in track call. Use event tags to pass in revenue value instead.')
199
+ if user_id.to_s.empty?
200
+ @logger.log(Logger::ERROR, 'User ID cannot be empty.')
201
+ return nil
169
202
  end
170
203
 
171
204
  return nil unless user_inputs_valid?(attributes, event_tags)
@@ -189,13 +222,18 @@ module Optimizely
189
222
  conversion_event = @event_builder.create_conversion_event(event_key, user_id, attributes,
190
223
  event_tags, experiment_variation_map)
191
224
  @logger.log(Logger::INFO,
192
- 'Dispatching conversion event to URL %s with params %s.' % [conversion_event.url,
193
- conversion_event.params])
225
+ "Dispatching conversion event to URL #{conversion_event.url} with params #{conversion_event.params}.")
194
226
  begin
195
227
  @event_dispatcher.dispatch_event(conversion_event)
196
228
  rescue => e
197
229
  @logger.log(Logger::ERROR, "Unable to dispatch conversion event. Error: #{e}")
198
230
  end
231
+
232
+ @notification_center.send_notifications(
233
+ NotificationCenter::NOTIFICATION_TYPES[:TRACK],
234
+ event_key, user_id, attributes, event_tags, conversion_event
235
+ )
236
+ nil
199
237
  end
200
238
 
201
239
  def is_feature_enabled(feature_flag_key, user_id, attributes = nil)
@@ -213,7 +251,17 @@ module Optimizely
213
251
  unless @is_valid
214
252
  logger = SimpleLogger.new
215
253
  logger.log(Logger::ERROR, InvalidDatafileError.new('is_feature_enabled').message)
216
- return nil
254
+ return false
255
+ end
256
+
257
+ unless feature_flag_key
258
+ @logger.log(Logger::ERROR, 'Feature flag key cannot be empty.')
259
+ return false
260
+ end
261
+
262
+ if user_id.to_s.empty?
263
+ @logger.log(Logger::ERROR, 'User ID cannot be empty.')
264
+ return false
217
265
  end
218
266
 
219
267
  feature_flag = @config.get_feature_flag_from_key(feature_flag_key)
@@ -223,23 +271,55 @@ module Optimizely
223
271
  end
224
272
 
225
273
  decision = @decision_service.get_variation_for_feature(feature_flag, user_id, attributes)
226
- unless decision.nil?
227
- variation = decision['variation']
228
- experiment = decision['experiment']
229
- unless experiment.nil?
230
- send_impression(experiment, variation['key'], user_id, attributes)
231
- else
232
- @logger.log(Logger::DEBUG,
233
- "The user '#{user_id}' is not being experimented on in feature '#{feature_flag_key}'.")
234
- end
274
+ if decision.nil?
275
+ @logger.log(Logger::INFO,
276
+ "Feature '#{feature_flag_key}' is not enabled for user '#{user_id}'.")
277
+ return false
278
+ end
235
279
 
236
- @logger.log(Logger::INFO, "Feature '#{feature_flag_key}' is enabled for user '#{user_id}'.")
237
- return true
280
+ variation = decision['variation']
281
+ unless variation['featureEnabled']
282
+ @logger.log(Logger::INFO,
283
+ "Feature '#{feature_flag_key}' is not enabled for user '#{user_id}'.")
284
+ return false
238
285
  end
239
286
 
240
- @logger.log(Logger::INFO,
241
- "Feature '#{feature_flag_key}' is not enabled for user '#{user_id}'.")
242
- false
287
+ if decision.source == Optimizely::DecisionService::DECISION_SOURCE_EXPERIMENT
288
+ # Send event if Decision came from an experiment.
289
+ send_impression(decision.experiment, variation['key'], user_id, attributes)
290
+ else
291
+ @logger.log(Logger::DEBUG,
292
+ "The user '#{user_id}' is not being experimented on in feature '#{feature_flag_key}'.")
293
+ end
294
+ @logger.log(Logger::INFO, "Feature '#{feature_flag_key}' is enabled for user '#{user_id}'.")
295
+
296
+ true
297
+ end
298
+
299
+ def get_enabled_features(user_id, attributes = nil)
300
+ # Gets keys of all feature flags which are enabled for the user.
301
+ # Args:
302
+ # user_id: ID for user.
303
+ # attributes: Dict representing user attributes.
304
+ # Returns:
305
+ # A List of feature flag keys that are enabled for the user.
306
+ #
307
+ enabled_features = []
308
+
309
+ unless @is_valid
310
+ logger = SimpleLogger.new
311
+ logger.log(Logger::ERROR, InvalidDatafileError.new('get_enabled_features').message)
312
+ return enabled_features
313
+ end
314
+
315
+ @config.feature_flags.each do |feature|
316
+ enabled_features.push(feature['key']) if is_feature_enabled(
317
+ feature['key'],
318
+ user_id,
319
+ attributes
320
+ ) == true
321
+ end
322
+ enabled_features.sort
243
323
  end
244
324
 
245
325
  def get_feature_variable_string(feature_flag_key, variable_key, user_id, attributes = nil)
@@ -256,12 +336,12 @@ module Optimizely
256
336
  variable_value = get_feature_variable_for_type(
257
337
  feature_flag_key,
258
338
  variable_key,
259
- Optimizely::Helpers::Constants::VARIABLE_TYPES["STRING"],
339
+ Optimizely::Helpers::Constants::VARIABLE_TYPES['STRING'],
260
340
  user_id,
261
341
  attributes
262
342
  )
263
343
 
264
- return variable_value
344
+ variable_value
265
345
  end
266
346
 
267
347
  def get_feature_variable_boolean(feature_flag_key, variable_key, user_id, attributes = nil)
@@ -278,12 +358,12 @@ module Optimizely
278
358
  variable_value = get_feature_variable_for_type(
279
359
  feature_flag_key,
280
360
  variable_key,
281
- Optimizely::Helpers::Constants::VARIABLE_TYPES["BOOLEAN"],
361
+ Optimizely::Helpers::Constants::VARIABLE_TYPES['BOOLEAN'],
282
362
  user_id,
283
363
  attributes
284
364
  )
285
365
 
286
- return variable_value
366
+ variable_value
287
367
  end
288
368
 
289
369
  def get_feature_variable_double(feature_flag_key, variable_key, user_id, attributes = nil)
@@ -300,12 +380,12 @@ module Optimizely
300
380
  variable_value = get_feature_variable_for_type(
301
381
  feature_flag_key,
302
382
  variable_key,
303
- Optimizely::Helpers::Constants::VARIABLE_TYPES["DOUBLE"],
383
+ Optimizely::Helpers::Constants::VARIABLE_TYPES['DOUBLE'],
304
384
  user_id,
305
385
  attributes
306
386
  )
307
387
 
308
- return variable_value
388
+ variable_value
309
389
  end
310
390
 
311
391
  def get_feature_variable_integer(feature_flag_key, variable_key, user_id, attributes = nil)
@@ -322,12 +402,12 @@ module Optimizely
322
402
  variable_value = get_feature_variable_for_type(
323
403
  feature_flag_key,
324
404
  variable_key,
325
- Optimizely::Helpers::Constants::VARIABLE_TYPES["INTEGER"],
405
+ Optimizely::Helpers::Constants::VARIABLE_TYPES['INTEGER'],
326
406
  user_id,
327
407
  attributes
328
408
  )
329
409
 
330
- return variable_value
410
+ variable_value
331
411
  end
332
412
 
333
413
  private
@@ -343,7 +423,23 @@ module Optimizely
343
423
  # attributes - Hash representing visitor attributes and values which need to be recorded.
344
424
  #
345
425
  # Returns the type-casted variable value.
346
- # Returns nil if the feature flag or variable are not found.
426
+ # Returns nil if the feature flag or variable or user ID is empty
427
+ # in case of variable type mismatch
428
+
429
+ unless feature_flag_key
430
+ @logger.log(Logger::ERROR, 'Feature flag key cannot be empty.')
431
+ return nil
432
+ end
433
+
434
+ unless variable_key
435
+ @logger.log(Logger::ERROR, 'Variable key cannot be empty.')
436
+ return nil
437
+ end
438
+
439
+ if user_id.to_s.empty?
440
+ @logger.log(Logger::ERROR, 'User ID cannot be empty.')
441
+ return nil
442
+ end
347
443
 
348
444
  feature_flag = @config.get_feature_flag_from_key(feature_flag_key)
349
445
  unless feature_flag
@@ -351,43 +447,40 @@ module Optimizely
351
447
  return nil
352
448
  end
353
449
 
354
- variable_value = nil
355
450
  variable = @config.get_feature_variable(feature_flag, variable_key)
356
- unless variable.nil?
357
- variable_value = variable['defaultValue']
358
451
 
452
+ # Error message logged in ProjectConfig- get_feature_flag_from_key
453
+ return nil if variable.nil?
454
+
455
+ # Returns nil if type differs
456
+ if variable['type'] != variable_type
457
+ @logger.log(Logger::WARN,
458
+ "Requested variable as type '#{variable_type}' but variable '#{variable_key}' is of type '#{variable['type']}'.")
459
+ return nil
460
+ else
359
461
  decision = @decision_service.get_variation_for_feature(feature_flag, user_id, attributes)
360
- unless decision
361
- @logger.log(Logger::INFO,
362
- "User '#{user_id}' was not bucketed into any variation for feature flag '#{feature_flag_key}'. Returning the default variable value '#{variable_value}'.")
363
- else
462
+ variable_value = variable['defaultValue']
463
+ if decision
364
464
  variation = decision['variation']
365
465
  variation_variable_usages = @config.variation_id_to_variable_usage_map[variation['id']]
366
466
  variable_id = variable['id']
367
- unless variation_variable_usages and variation_variable_usages.key?(variable_id)
368
- variation_key = variation['key']
369
- @logger.log(Logger::DEBUG,
370
- "Variable '#{variable_key}' is not used in variation '#{variation_key}'. Returning the default variable value '#{variable_value}'."
371
- )
372
- else
467
+ if variation_variable_usages&.key?(variable_id)
373
468
  variable_value = variation_variable_usages[variable_id]['value']
374
469
  @logger.log(Logger::INFO,
375
- "Got variable value '#{variable_value}' for variable '#{variable_key}' of feature flag '#{feature_flag_key}'.")
470
+ "Got variable value '#{variable_value}' for variable '#{variable_key}' of feature flag '#{feature_flag_key}'.")
471
+ else
472
+ @logger.log(Logger::DEBUG,
473
+ "Variable '#{variable_key}' is not used in variation '#{variation['key']}'. Returning the default variable value '#{variable_value}'.")
376
474
  end
475
+ else
476
+ @logger.log(Logger::INFO,
477
+ "User '#{user_id}' was not bucketed into any variation for feature flag '#{feature_flag_key}'. Returning the default variable value '#{variable_value}'.")
377
478
  end
378
479
  end
379
480
 
380
- unless variable_value.nil?
381
- actual_variable_type = variable['type']
382
- unless variable_type == actual_variable_type
383
- @logger.log(Logger::WARN,
384
- "Requested variable type '#{variable_type}' but variable '#{variable_key}' is of type '#{actual_variable_type}'.")
385
- end
481
+ variable_value = Helpers::VariableType.cast_value_to_type(variable_value, variable_type, @logger)
386
482
 
387
- variable_value = Helpers::VariableType.cast_value_to_type(variable_value, variable_type, @logger)
388
- end
389
-
390
- return variable_value
483
+ variable_value
391
484
  end
392
485
 
393
486
  def get_valid_experiments_for_event(event_key, user_id, attributes)
@@ -426,13 +519,9 @@ module Optimizely
426
519
  #
427
520
  # Returns boolean True if inputs are valid. False otherwise.
428
521
 
429
- if !attributes.nil? && !attributes_valid?(attributes)
430
- return false
431
- end
522
+ return false if !attributes.nil? && !attributes_valid?(attributes)
432
523
 
433
- if !event_tags.nil? && !event_tags_valid?(event_tags)
434
- return false
435
- end
524
+ return false if !event_tags.nil? && !event_tags_valid?(event_tags)
436
525
 
437
526
  true
438
527
  end
@@ -457,12 +546,12 @@ module Optimizely
457
546
 
458
547
  def validate_instantiation_options(datafile, skip_json_validation)
459
548
  unless skip_json_validation
460
- raise InvalidInputError.new('datafile') unless Helpers::Validator.datafile_valid?(datafile)
549
+ raise InvalidInputError, 'datafile' unless Helpers::Validator.datafile_valid?(datafile)
461
550
  end
462
551
 
463
- raise InvalidInputError.new('logger') unless Helpers::Validator.logger_valid?(@logger)
464
- raise InvalidInputError.new('error_handler') unless Helpers::Validator.error_handler_valid?(@error_handler)
465
- raise InvalidInputError.new('event_dispatcher') unless Helpers::Validator.event_dispatcher_valid?(@event_dispatcher)
552
+ raise InvalidInputError, 'logger' unless Helpers::Validator.logger_valid?(@logger)
553
+ raise InvalidInputError, 'error_handler' unless Helpers::Validator.error_handler_valid?(@error_handler)
554
+ raise InvalidInputError, 'event_dispatcher' unless Helpers::Validator.event_dispatcher_valid?(@event_dispatcher)
466
555
  end
467
556
 
468
557
  def send_impression(experiment, variation_key, user_id, attributes = nil)
@@ -470,13 +559,17 @@ module Optimizely
470
559
  variation_id = @config.get_variation_id_from_key(experiment_key, variation_key)
471
560
  impression_event = @event_builder.create_impression_event(experiment, variation_id, user_id, attributes)
472
561
  @logger.log(Logger::INFO,
473
- 'Dispatching impression event to URL %s with params %s.' % [impression_event.url,
474
- impression_event.params])
562
+ "Dispatching impression event to URL #{impression_event.url} with params #{impression_event.params}.")
475
563
  begin
476
564
  @event_dispatcher.dispatch_event(impression_event)
477
565
  rescue => e
478
566
  @logger.log(Logger::ERROR, "Unable to dispatch impression event. Error: #{e}")
479
567
  end
568
+ variation = @config.get_variation_from_id(experiment_key, variation_id)
569
+ @notification_center.send_notifications(
570
+ NotificationCenter::NOTIFICATION_TYPES[:ACTIVATE],
571
+ experiment, user_id, attributes, variation, impression_event
572
+ )
480
573
  end
481
574
  end
482
575
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
- # Copyright 2016, Optimizely and contributors
4
+ # Copyright 2016-2017, Optimizely and contributors
3
5
  #
4
6
  # Licensed under the Apache License, Version 2.0 (the "License");
5
7
  # you may not use this file except in compliance with the License.
@@ -41,8 +43,9 @@ module Optimizely
41
43
  # Return true if any one of the audience conditions are met
42
44
  @condition_evaluator = ConditionEvaluator.new(attributes)
43
45
  audience_ids.each do |audience_id|
44
- audience_conditions = config.get_audience_conditions_from_id(audience_id)
45
- audience_conditions = JSON.load(audience_conditions)
46
+ audience = config.get_audience_from_id(audience_id)
47
+ audience_conditions = audience['conditions']
48
+ audience_conditions = JSON.parse(audience_conditions)
46
49
  return true if @condition_evaluator.evaluate(audience_conditions)
47
50
  end
48
51
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  #
2
4
  # Copyright 2016-2017, Optimizely and contributors
3
5
  #
@@ -20,7 +22,7 @@ module Optimizely
20
22
  class Bucketer
21
23
  # Optimizely bucketing algorithm that evenly distributes visitors.
22
24
 
23
- BUCKETING_ID_TEMPLATE = '%{user_id}%{entity_id}'
25
+ BUCKETING_ID_TEMPLATE = '%<bucketing_id>s%<entity_id>s'
24
26
  HASH_SEED = 1
25
27
  MAX_HASH_VALUE = 2**32
26
28
  MAX_TRAFFIC_VALUE = 10_000
@@ -35,13 +37,15 @@ module Optimizely
35
37
  @config = config
36
38
  end
37
39
 
38
- def bucket(experiment, user_id)
40
+ def bucket(experiment, bucketing_id, user_id)
39
41
  # Determines ID of variation to be shown for a given experiment key and user ID.
40
42
  #
41
43
  # experiment - Experiment for which visitor is to be bucketed.
44
+ # bucketing_id - String A customer-assigned value used to generate the bucketing key
42
45
  # user_id - String ID for user.
43
46
  #
44
47
  # Returns variation in which visitor with ID user_id has been placed. Nil if no variation.
48
+ return nil if experiment.nil?
45
49
 
46
50
  # check if experiment is in a group; if so, check if user is bucketed into specified experiment
47
51
  experiment_id = experiment['id']
@@ -51,7 +55,7 @@ module Optimizely
51
55
  group = @config.group_key_map.fetch(group_id)
52
56
  if Helpers::Group.random_policy?(group)
53
57
  traffic_allocations = group.fetch('trafficAllocation')
54
- bucketed_experiment_id = find_bucket(user_id, group_id, traffic_allocations)
58
+ bucketed_experiment_id = find_bucket(bucketing_id, user_id, group_id, traffic_allocations)
55
59
  # return if the user is not bucketed into any experiment
56
60
  unless bucketed_experiment_id
57
61
  @config.logger.log(Logger::INFO, "User '#{user_id}' is in no experiment.")
@@ -76,7 +80,7 @@ module Optimizely
76
80
  end
77
81
 
78
82
  traffic_allocations = experiment['trafficAllocation']
79
- variation_id = find_bucket(user_id, experiment_id, traffic_allocations)
83
+ variation_id = find_bucket(bucketing_id, user_id, experiment_id, traffic_allocations)
80
84
  if variation_id && variation_id != ''
81
85
  variation = @config.get_variation_from_id(experiment_key, variation_id)
82
86
  variation_key = variation ? variation['key'] : nil
@@ -96,18 +100,19 @@ module Optimizely
96
100
  nil
97
101
  end
98
102
 
99
- def find_bucket(user_id, parent_id, traffic_allocations)
103
+ def find_bucket(bucketing_id, user_id, parent_id, traffic_allocations)
100
104
  # Helper function to find the matching entity ID for a given bucketing value in a list of traffic allocations.
101
105
  #
106
+ # bucketing_id - String A customer-assigned value user to generate bucketing key
102
107
  # user_id - String ID for user
103
108
  # parent_id - String entity ID to use for bucketing ID
104
109
  # traffic_allocations - Array of traffic allocations
105
110
  #
106
111
  # Returns entity ID corresponding to the provided bucket value or nil if no match is found.
107
-
108
- bucketing_id = sprintf(BUCKETING_ID_TEMPLATE, user_id: user_id, entity_id: parent_id)
109
- bucket_value = generate_bucket_value(bucketing_id)
110
- @config.logger.log(Logger::DEBUG, "Assigned bucket #{bucket_value} to user '#{user_id}'.")
112
+ bucketing_key = format(BUCKETING_ID_TEMPLATE, bucketing_id: bucketing_id, entity_id: parent_id)
113
+ bucket_value = generate_bucket_value(bucketing_key)
114
+ @config.logger.log(Logger::DEBUG, "Assigned bucket #{bucket_value} to user '#{user_id}' "\
115
+ "with bucketing ID: '#{bucketing_id}'.")
111
116
 
112
117
  traffic_allocations.each do |traffic_allocation|
113
118
  current_end_of_range = traffic_allocation['endOfRange']
@@ -122,25 +127,25 @@ module Optimizely
122
127
 
123
128
  private
124
129
 
125
- def generate_bucket_value(bucketing_id)
130
+ def generate_bucket_value(bucketing_key)
126
131
  # Helper function to generate bucket value in half-closed interval [0, MAX_TRAFFIC_VALUE).
127
132
  #
128
- # bucketing_id - String ID for bucketing.
133
+ # bucketing_key - String - Value used to generate bucket value
129
134
  #
130
- # Returns bucket value corresponding to the provided bucketing ID.
135
+ # Returns bucket value corresponding to the provided bucketing key.
131
136
 
132
- ratio = (generate_unsigned_hash_code_32_bit(bucketing_id)).to_f / MAX_HASH_VALUE
137
+ ratio = generate_unsigned_hash_code_32_bit(bucketing_key).to_f / MAX_HASH_VALUE
133
138
  (ratio * MAX_TRAFFIC_VALUE).to_i
134
139
  end
135
140
 
136
- def generate_unsigned_hash_code_32_bit(bucketing_id)
141
+ def generate_unsigned_hash_code_32_bit(bucketing_key)
137
142
  # Helper function to retreive hash code
138
143
  #
139
- # bucketing_id - String ID for bucketing.
144
+ # bucketing_key - String - Value used for the key of the murmur hash
140
145
  #
141
146
  # Returns hash code which is a 32 bit unsigned integer.
142
147
 
143
- MurmurHash3::V32.str_hash(bucketing_id, @bucket_seed) & UNSIGNED_MAX_32_BIT_VALUE
148
+ MurmurHash3::V32.str_hash(bucketing_key, @bucket_seed) & UNSIGNED_MAX_32_BIT_VALUE
144
149
  end
145
150
  end
146
151
  end