Skip to content

Instantly share code, notes, and snippets.

@ismasan
Created September 13, 2023 21:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ismasan/3619244fd11876f5191b1aa08aaca7f7 to your computer and use it in GitHub Desktop.
Save ismasan/3619244fd11876f5191b1aa08aaca7f7 to your computer and use it in GitHub Desktop.
require 'digest'
class ConsistentHash
Node = Data.define(:position, :updated_at)
def initialize(size = 1)
@hash_ring = {}
(0...size).each { |i| add(i) }
end
def size
@hash_ring.size
end
def add(pos)
hash = hash_value(pos)
@hash_ring[hash] = Node.new(pos, Time.now.utc)
end
def resolve(key)
hash = hash_value(key)
ring = @hash_ring.keys.sort
k = ring.find { |h| h >= hash } || ring.first
@hash_ring[k]
end
def checkin(pos)
hash = hash_value(pos)
add(pos) unless @hash_ring.key?(hash)
ring = @hash_ring.keys.sort
k = ring.find { |h| h >= hash } || ring.first
node = @hash_ring[k]
@hash_ring[k] = node.with(updated_at: Time.now.utc)
end
def remove(pos)
hash = hash_value(pos)
@hash_ring.delete(hash)
end
def rebalance
now = Time.now.utc
@hash_ring.each do |hash, node|
@hash_ring.delete(hash) if (now - node.updated_at) > 10
end
end
private
def hash_value(value)
Digest::SHA256.digest(value.to_s).sum % 360
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment