class VWO::BucketingService

Constants

FILE
MAX_HASH_VALUE
U_MAX_32_BIT

Public Class Methods

new() click to toggle source
# File lib/vwo/bucketing_service.rb, line 20
def initialize
  @logger = CustomLogger.get_instance
end

Public Instance Methods

bucket_user_to_variation(user_id, campaign) click to toggle source

Validates the User ID and Generates Variation into which the User is bucketed in.

@param :user_id The unique ID assigned to User @param :campaign The Campaign of which User is a part of

@return[Hash|nil} Variation data into which user is bucketed in

or nil if not
# File lib/vwo/bucketing_service.rb, line 65
def bucket_user_to_variation(user_id, campaign)
  unless valid_value?(user_id)
    @logger.log(
      LogLevelEnum::ERROR,
      format(LogMessageEnum::ErrorMessages::INVALID_USER_ID, file: FILE, user_id: user_id, method: 'bucket_user_to_variation')
    )
    return
  end

  unless campaign
    @logger.log(
      LogLevelEnum::ERROR,
      format(LogMessageEnum::ErrorMessages::INVALID_CAMPAIGN, file: FILE, method: 'is_user_part_of_campaign')
    )
    return
  end

  hash_value = MurmurHash3::V32.str_hash(user_id, SEED_VALUE) & U_MAX_32_BIT
  normalize = MAX_TRAFFIC_VALUE / campaign['percentTraffic']
  multiplier = normalize / 100
  bucket_value = generate_bucket_value(
    hash_value,
    MAX_TRAFFIC_VALUE,
    multiplier
  )

  @logger.log(
    LogLevelEnum::DEBUG,
    format(
      LogMessageEnum::DebugMessages::VARIATION_HASH_BUCKET_VALUE,
      file: FILE,
      user_id: user_id,
      campaign_test_key: campaign['key'],
      percent_traffic: campaign['percentTraffic'],
      bucket_value: bucket_value,
      hash_value: hash_value
    )
  )
  get_variation(campaign, bucket_value)
end
user_part_of_campaign?(user_id, campaign) click to toggle source

Calculate if this user should become part of the campaign or not @param :user_id The unique ID assigned to a user @param :campaign For getting traffic allotted to the campaign @return If User is a part of Campaign or not

# File lib/vwo/bucketing_service.rb, line 29
def user_part_of_campaign?(user_id, campaign)
  unless valid_value?(user_id)
    @logger.log(
      LogLevelEnum::ERROR,
      format(LogMessageEnum::ErrorMessages::INVALID_USER_ID, file: FILE, user_id: user_id, method: 'is_user_part_of_campaign')
    )
    return false
  end

  if campaign.nil?
    @logger.log(
      LogLevelEnum::ERROR,
      format(LogMessageEnum::ErrorMessages::INVALID_CAMPAIGN, file: FILE, method: 'is_user_part_of_campaign')
    )
    return false
  end

  traffic_allocation = campaign['percentTraffic']

  value_assigned_to_user = get_bucket_value_for_user(user_id)
  is_user_part = (value_assigned_to_user != 0) && value_assigned_to_user <= traffic_allocation
  @logger.log(
    LogLevelEnum::INFO,
    format(LogMessageEnum::InfoMessages::USER_ELIGIBILITY_FOR_CAMPAIGN, file: FILE, user_id: user_id, is_user_part: is_user_part)
  )
  is_user_part
end

Private Instance Methods

generate_bucket_value(hash_value, max_value, multiplier = 1) click to toggle source

Generates Bucket Value of the User by hashing the User ID by murmurHash And scaling it down.

@param :hash_value HashValue generated after hashing @param :max_value The value up-to which hashValue needs to be scaled @param :multiplier @return Bucket Value of the User

# File lib/vwo/bucketing_service.rb, line 152
def generate_bucket_value(hash_value, max_value, multiplier = 1)
  ratio = hash_value.to_f / MAX_HASH_VALUE
  multiplied_value = (max_value * ratio + 1) * multiplier
  multiplied_value.to_i
end
get_bucket_value_for_user(user_id) click to toggle source

Validates the User ID and generates Bucket Value of the User by hashing the userId by murmurHash and scaling it down.

@param :user_id The unique ID assigned to User @return The bucket Value allotted to User

(between 1 to $this->$MAX_TRAFFIC_PERCENT)
# File lib/vwo/bucketing_service.rb, line 127
def get_bucket_value_for_user(user_id)
  hash_value = MurmurHash3::V32.str_hash(user_id, SEED_VALUE) & U_MAX_32_BIT
  bucket_value = generate_bucket_value(hash_value, MAX_TRAFFIC_PERCENT)

  @logger.log(
    LogLevelEnum::DEBUG,
    format(
      LogMessageEnum::DebugMessages::USER_HASH_BUCKET_VALUE,
      file: FILE,
      hash_value: hash_value,
      bucket_value: bucket_value,
      user_id: user_id
    )
  )
  bucket_value
end
get_variation(campaign, bucket_value) click to toggle source

Returns the Variation by checking the Start and End Bucket Allocations of each Variation

@param :campaign Which contains the variations @param :bucket_value The bucket Value of the user @return Variation data allotted to the user or None if not

# File lib/vwo/bucketing_service.rb, line 115
def get_variation(campaign, bucket_value)
  campaign['variations'].find do |variation|
    (variation['start_variation_allocation']..variation['end_variation_allocation']).cover?(bucket_value)
  end
end