class LetsShard

Constants

DEFAULT_SLOTS
VERSION

Attributes

shards[R]

Public Class Methods

new(objects, weights: []) click to toggle source
# File lib/lets_shard.rb, line 10
def initialize(objects, weights: [])
  validate_parameters!(objects, weights)

  @objects = objects
  @weights = weights.any? ? weights : Array.new(@objects.size, 1)
  @slots = [DEFAULT_SLOTS, weights.sum].max

  set_unit_weight!
  set_remainder_slots!
  generate_shards!
end

Public Instance Methods

get_object(key) click to toggle source
# File lib/lets_shard.rb, line 30
def get_object(key)
  get_shard(key).object
end
get_shard(key) click to toggle source
# File lib/lets_shard.rb, line 22
def get_shard(key)
  hkey = get_hkey(key)

  @shards.find do |shard|
    (shard.start_slot..shard.end_slot).include?(hkey)
  end
end

Private Instance Methods

generate_shards!() click to toggle source
# File lib/lets_shard.rb, line 36
def generate_shards!
  @shards = []
  start_slot = 0

  @objects.each_with_index do |object, index|
    end_slot = start_slot + (@weights[index] * @unit_weight) - 1

    if @remainder_slots > 0
      slots_to_add = [@weights[index], @remainder_slots].min
      end_slot += slots_to_add
      @remainder_slots -= slots_to_add
    end

    @shards << Shard.new(object, start_slot, end_slot)

    start_slot = end_slot + 1
  end
end
get_hkey(key) click to toggle source
# File lib/lets_shard.rb, line 67
def get_hkey(key)
  Digest.crc16(key.to_s) % @slots
end
set_remainder_slots!() click to toggle source
# File lib/lets_shard.rb, line 63
def set_remainder_slots!
  @remainder_slots = @slots - (@unit_weight * weights_sum)
end
set_unit_weight!() click to toggle source
# File lib/lets_shard.rb, line 59
def set_unit_weight!
  @unit_weight = @slots / weights_sum
end
validate_parameters!(objects, weights) click to toggle source
# File lib/lets_shard.rb, line 71
def validate_parameters!(objects, weights)
  unless objects.is_a?(Array)
    raise LetsShardError, 'Objects should be an array!'
  end

  unless weights.is_a?(Array)
    raise LetsShardError, 'Weights should be an array!'
  end

  unless objects.any?
    raise LetsShardError, 'Objects array should not be empty!'
  end

  if weights.any? && (objects.size != weights.size)
    raise LetsShardError, 'Weights should be as size as objects!'
  end

  if weights.any? && !weights.all? { |w| w.is_a?(Integer) }
    raise LetsShardError, 'All weights should be integers!'
  end
end
weights_sum() click to toggle source
# File lib/lets_shard.rb, line 55
def weights_sum
  @weights.inject(0, :+)
end