Class: ZK::Election::Base

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/z_k/election.rb

Direct Known Subclasses

Candidate, Observer

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

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

Returns a new instance of Base.



65
66
67
68
69
70
71
# File 'lib/z_k/election.rb', line 65

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

Instance Attribute Details

#root_election_nodeObject (readonly)

Returns the value of attribute root_election_node.



63
64
65
# File 'lib/z_k/election.rb', line 63

def root_election_node
  @root_election_node
end

#vote_pathObject (readonly)

Returns the value of attribute vote_path.



63
64
65
# File 'lib/z_k/election.rb', line 63

def vote_path
  @vote_path
end

#zkObject (readonly)

Returns the value of attribute zk.



63
64
65
# File 'lib/z_k/election.rb', line 63

def zk
  @zk
end

Instance Method Details

#cast_ballot!(data) ⇒ Object



85
86
87
88
89
90
91
# File 'lib/z_k/election.rb', line 85

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

#create_root_path!Object (protected)



143
144
145
# File 'lib/z_k/election.rb', line 143

def create_root_path!
  @zk.mkdir_p(root_vote_path)
end

#digit(path) ⇒ Object (protected)



151
152
153
154
# File 'lib/z_k/election.rb', line 151

def digit(path)
  path[/\d+$/].to_i

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



81
82
83
# File 'lib/z_k/election.rb', line 81

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)


94
95
96
# File 'lib/z_k/election.rb', line 94

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



99
100
101
102
# File 'lib/z_k/election.rb', line 99

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. The given block will always be called on a background thread.



106
107
108
109
110
111
112
113
114
115
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
# File 'lib/z_k/election.rb', line 106

def on_leader_ack(&block)
  creation_sub = @zk.watcher.register(leader_ack_path) do |event|
    case event.type
    when Zookeeper::ZOO_CREATED_EVENT, Zookeeper::ZOO_CHANGED_EVENT
      begin
        logger.debug { "in #{leader_ack_path} watcher, got creation event, notifying" }
        block.call
      ensure
        creation_sub.unregister
      end
    else
      if @zk.exists?(leader_ack_path, :watch => true)
        begin
          logger.debug { "in #{leader_ack_path} watcher, node created behind our back, notifying" }
          block.call
        ensure
          creation_sub.unregister
        end
      else
        logger.debug { "in #{leader_ack_path} watcher, got non-creation event, re-watching" }
      end
    end
  end

  @zk.defer do
    if @zk.exists?(leader_ack_path, :watch => true)
      logger.debug { "on_leader_ack, #{leader_ack_path} exists, calling block" }
      begin
        block.call
      ensure
        creation_sub.unregister if creation_sub
      end
    end
  end
end

#root_vote_pathObject

holds the ephemeral nodes of this election



74
75
76
# File 'lib/z_k/election.rb', line 74

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

#safe_call(*callbacks) ⇒ Object (protected)



156
157
158
159
160
161
162
163
164
165
# File 'lib/z_k/election.rb', line 156

def safe_call(*callbacks)
  callbacks.each do |cb|
    begin
      cb.call
    rescue Exception => e
      logger.error { "Error caught in user supplied callback" }
      logger.error { e.to_std_format }
    end
  end
end

#vote_basenameObject (protected)



147
148
149
# File 'lib/z_k/election.rb', line 147

def vote_basename
  vote_path and File.basename(vote_path)
end