optimizely-sdk 2.0.0.beta → 2.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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