Exception: SplitIoClient::Splitter

Inherits:
NoMethodError
  • Object
show all
Defined in:
lib/splitclient-rb/engine/evaluator/splitter.rb

Overview

Misc class in charge of providing hash functions and determination of treatment based on concept of buckets based on provided key

Class Method Summary collapse

Class Method Details

.bucket(hash_value) ⇒ Object

returns bucket value for the given hash value

Parameters:

  • hash_value (string)

    hash value



113
114
115
# File 'lib/splitclient-rb/engine/evaluator/splitter.rb', line 113

def bucket(hash_value)
  (hash_value.abs % 100) + 1
end

.count_hash(key, seed, legacy) ⇒ Object

returns a hash value for the give key, seed pair

Parameters:

  • key (String)

    user key

  • seed (Fixnum)

    seed for the user key



48
49
50
# File 'lib/splitclient-rb/engine/evaluator/splitter.rb', line 48

def count_hash(key, seed, legacy)
  legacy ? legacy_hash(key, seed) : murmur_hash(key, seed)
end

.get_treatment(id, seed, partitions, legacy_algo) ⇒ Object

gets the appropriate treatment based on id, seed and partition value

Parameters:

  • id (string)

    user key

  • seed (number)

    seed for the user key

  • partitions (object)

    array of partitions



28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/splitclient-rb/engine/evaluator/splitter.rb', line 28

def get_treatment(id, seed, partitions, legacy_algo)
  legacy = (legacy_algo == 1 || legacy_algo == nil) ? true : false

  if partitions.empty?
    return SplitIoClient::Engine::Models::Treatment::CONTROL
  end

  if hundred_percent_one_treatment?(partitions)
    return (partitions.first).treatment
  end

  return get_treatment_for_key(bucket(count_hash(id, seed, legacy_algo)), partitions)
end

.get_treatment_for_key(bucket, partitions) ⇒ Object

returns the treatment for a bucket given the partitions

Parameters:

  • bucket (number)

    bucket value

  • parittions (object)

    array of partitions



95
96
97
98
99
100
101
102
103
104
105
# File 'lib/splitclient-rb/engine/evaluator/splitter.rb', line 95

def get_treatment_for_key(bucket, partitions)
  buckets_covered_thus_far = 0
  partitions.each do |p|
    unless p.is_empty?
      buckets_covered_thus_far += p.size
      return p.treatment if buckets_covered_thus_far >= bucket
    end
  end

  return SplitIoClient::Engine::Models::Treatment::CONTROL
end

.hundred_percent_one_treatment?(partitions) ⇒ boolean

Checks if the partiotion size is 100%

Parameters:

  • partitions (object)

    array of partitions

Returns:

  • (boolean)

    true if partition is 100% false otherwise



16
17
18
# File 'lib/splitclient-rb/engine/evaluator/splitter.rb', line 16

def hundred_percent_one_treatment?(partitions)
  (partitions.size != 1) ? false : (partitions.first.size == 100)
end

.legacy_hash(key, seed) ⇒ Object



56
57
58
59
60
61
62
63
64
# File 'lib/splitclient-rb/engine/evaluator/splitter.rb', line 56

def legacy_hash(key, seed)
  h = 0

  for i in 0..key.length-1
    h = to_int32(31 * h + key[i].ord)
  end

  h^seed
end

.murmur_hash(key, seed) ⇒ Object



52
53
54
# File 'lib/splitclient-rb/engine/evaluator/splitter.rb', line 52

def murmur_hash(key, seed)
  Digest::MurmurHash3_x86_32.rawdigest(key, [seed].pack('L'))
end

.to_int32(number) ⇒ int

misc method to convert ruby number to int 32 since overflow is handled different to java

Parameters:

  • number (number)

    ruby number value

Returns:

  • (int)

    returns the int 32 value of the provided number



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/splitclient-rb/engine/evaluator/splitter.rb', line 72

def to_int32(number)
  begin
    sign = number < 0 ? -1 : 1
    abs = number.abs
    return 0 if abs == 0 || abs == Float::INFINITY
  rescue
    return 0
  end

  pos_int = sign * abs.floor
  int_32bit = pos_int % 2**32

  return int_32bit - 2**32 if int_32bit >= 2**31
  int_32bit
end