Skip to content

Instantly share code, notes, and snippets.

@davidcollom
Forked from fabrizioc1/election_candidate.rb
Last active January 20, 2016 10:38
Show Gist options
  • Save davidcollom/5c7775b951df0b935d9b to your computer and use it in GitHub Desktop.
Save davidcollom/5c7775b951df0b935d9b to your computer and use it in GitHub Desktop.
Zookeeper leader election using Ruby
# http://zookeeper.apache.org/doc/r3.3.4/recipes.html#sc_leaderElection
require 'rubygems'
require 'bundler/setup'
require 'zookeeper'
require 'hashie'
class ElectionCandidate
attr_reader :zookeeper, :children, :root_path, :node_path, :my_path
attr_accessor :logger
def initialize zookeeper_uri, root_path, node_path, logger=Logger.new(STDOUT)
root_path = "/#{root_path}" if root_path[0] !='/'
@root_path, @node_path, @logger = root_path, node_path, logger
@zookeeper = Zookeeper.new(zookeeper_uri)
root_path_create! unless root_path_exists?
register!
end
def root_path_create!
resp = @zookeeper.create(path: @root_path, data: @root_path)
raise "Unable to create root node" if resp[:path] == @root_path
resp
end
def root_path_exists?
Hashie::Mash.new(@zookeeper.get(path: @root_path)).stat.exists?
end
def register!
raise "Already registered: #{@my_path}" if registered?
path = "#{@root_path}/#{@node_path}"
@logger.info "Registering node..#{path}"
result = Hashie::Mash.new(@zookeeper.create(path: path, data: path, ephemeral: true, sequence: true))
if result.rc == 0
@my_path = result.path
@logger.info([self.class, __method__].join('.')){ "My node..#{@my_path}" }
end
end
def unregister!
raise "Not registered" unless registered?
resp = Hashie::Mash.new(@zookeeper.delete(path: @my_path))
if resp.rc == 0
@logger.info([self.class, __method__].join('.')){ "Succesfully unregistered #{@my_path}"}
@my_path = nil
return true
end
false
end
def registered?
!@my_path.nil? && Hashie::Mash.new(@zookeeper.get(path: @my_path)).stat.exists?
end
def candidates
Hashie::Mash.new(@zookeeper.get_children(path: @root_path))
end
def leader?
result = candidates
@children = result.children
@logger.info([self.class, __method__].join('.')){"Found #{@children.size} children.."}
@logger.debug([self.class, __method__].join('.')){@children}
@logger.error([self.class, __method__].join('.')){"ERROR: #{result}"} if result.rc != 0
leader = result.children.select{|c| c[/#{@node_path}/] }.sort.first
leader_path = "#{@root_path}/#{leader}"
@logger.debug([self.class,__method__].join('.')){"#{leader_path} is leader"}
result.rc == 0 && result.children && @my_path == leader_path
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment