Class: ZK::Election::Base

Inherits:
Object
  • Object
show all
Includes:
Logger
Defined in:
lib/zk/election.rb

Direct Known Subclasses

Candidate, Observer

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Logger

#logger, wrapped_logger, wrapped_logger=

Constructor Details

#initialize(client, name, opts = {}) ⇒ Base

Returns a new instance of Base.



67
68
69
70
71
72
73
74
# File 'lib/zk/election.rb', line 67

def initialize(client, name, opts={})
  @zk = client
  @name = name
  opts = DEFAULT_OPTS.merge(opts)
  @root_election_node = opts[:root_election_node]
  @mutex = Monitor.new
  @closed = false
end

Instance Attribute Details

#root_election_nodeObject (readonly)

Returns the value of attribute root_election_node.



65
66
67
# File 'lib/zk/election.rb', line 65

def root_election_node
  @root_election_node
end

#vote_pathObject (readonly)

Returns the value of attribute vote_path.



65
66
67
# File 'lib/zk/election.rb', line 65

def vote_path
  @vote_path
end

#zkObject (readonly)

Returns the value of attribute zk.



65
66
67
# File 'lib/zk/election.rb', line 65

def zk
  @zk
end

Instance Method Details

#cast_ballot!(data) ⇒ Object



95
96
97
98
99
100
101
# File 'lib/zk/election.rb', line 95

def cast_ballot!(data)
  return if @vote_path
  create_root_path!
  @vote_path = @zk.create("#{root_vote_path}/#{VOTE_PREFIX}", data, :mode => :ephemeral_sequential)
rescue Exceptions::NoNode
  retry
end

#closeObject



76
77
78
79
80
81
# File 'lib/zk/election.rb', line 76

def close
  @mutex.synchronize do
    return if @closed
    @closed = true
  end
end

#leader_ack_pathObject

this znode will be created as an acknowledgement by the leader that it's aware of its status as the new leader and has run its procedures to become master



91
92
93
# File 'lib/zk/election.rb', line 91

def leader_ack_path
  @leader_ack_path ||= "#{root_vote_path}/leader_ack"
end

#leader_acked?(watch = false) ⇒ Boolean

has the leader acknowledged their role?

Returns:

  • (Boolean)


104
105
106
# File 'lib/zk/election.rb', line 104

def leader_acked?(watch=false)
  @zk.exists?(leader_ack_path, :watch => watch)
end

#leader_dataObject

return the data from the current leader or nil if there is no current leader



109
110
111
112
# File 'lib/zk/election.rb', line 109

def leader_data
  @zk.get(leader_ack_path).first
rescue Exceptions::NoNode
end

#on_leader_ack(&block) ⇒ Object

Asynchronously call the block when the leader has acknowledged its role.



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/zk/election.rb', line 116

def on_leader_ack(&block)
  creation_sub = @zk.register(leader_ack_path, :only => [:created, :changed]) do |event|
    return if @closed
    begin
      logger.debug { "in #{leader_ack_path} watcher, got creation event, notifying" }
      safe_call(block)
    ensure
      creation_sub.unregister
    end
  end

  deletion_sub = @zk.register(leader_ack_path, :only => [:deleted, :child]) do |event|
    if @zk.exists?(leader_ack_path, :watch => true)
      return if @closed
      begin
        logger.debug { "in #{leader_ack_path} watcher, node created behind our back, notifying" }
        safe_call(block)
      ensure
        creation_sub.unregister
      end
    else
      logger.debug { "in #{leader_ack_path} watcher, got non-creation event, re-watching" }
    end
  end

  subs = [creation_sub, deletion_sub]

  if @zk.exists?(leader_ack_path, :watch => true)
    logger.debug { "on_leader_ack, #{leader_ack_path} exists, calling block" }
    begin
      safe_call(block)
    ensure
      subs.each { |s| s.unregister }
    end
  end
end

#root_vote_pathObject

holds the ephemeral nodes of this election



84
85
86
# File 'lib/zk/election.rb', line 84

def root_vote_path #:nodoc:
  @root_vote_path ||= "#{@root_election_node}/#{@name.gsub('/', '__')}"
end