def request_vote_from_peers(self): if self.state != ConsensusState.CANDIDATE: return votes_received = 1 peers = {server: address for server, address in cluster_info_by_name.items() if self.raft_server.name != server} # We can use a with statement to ensure threads are cleaned up promptly with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: future_to_server = {executor.submit(self.do_rpc_request, server, address): server for server, address in peers.items()} for future in concurrent.futures.as_completed(future_to_server): server = future_to_server[future] try: data = future.result() except Exception as exc: print(f"{self.raft_server.name} : [ {server} ] generated an exception {exc}") else: print(f"{self.raft_server.name} : Result from {server} of the Request Vote response {data}") if self.state != ConsensusState.CANDIDATE: print( f"{self.raft_server.name} : while waiting for the reply state changed {state_to_name[self.state]}") return if data.VoteGranted: votes_received = votes_received + 1 print(f"{self.raft_server.name} : For a current term {self.current_term} the votes received {votes_received}") nodes_that_can_fail = (len(cluster_info_by_name) - 1) / 2 if votes_received > nodes_that_can_fail: print(f"{self.raft_server.name} : Got majority of votes .. Lets roll and become leader") self.become_leader() # Run timer in case of split votes self.run_election_timer()
def send_heart_beat(self): peers = {server: address for server, address in cluster_info_by_name.items() if self.raft_server.name != server} # We can use a with statement to ensure threads are cleaned up promptly with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: future_to_server = {executor.submit(self.do_heartbeat_rpc_request, server, address): server for server, address in peers.items()} for future in concurrent.futures.as_completed(future_to_server): server = future_to_server[future] try: data = future.result() except Exception as exc: print(f"{self.raft_server.name} : [ {server} ] generated an exception {exc}") else: print(f"{self.raft_server.name} : Result from {server} of the Heart Beat response {data}") if data.Term > self.current_term: print(f"{self.raft_server.name} : Term out of date in Heartbeat reply") self.become_follower(data.Term) return
def connect_rpc_clients(self): while True: for server, address in cluster_info_by_name.items(): if server != self.name: if self.consensusModule.peers.get(server, None) is None: print( f"{self.name} : trying to connect to {server} at {address}" ) try: remote = RPCProxy(cluster_info_by_name[server], authkey=b"peekaboo", timeout=2) except Exception as e: print( f"{self.name} : [ {server} ] generated an exception: {e}" ) else: self.consensusModule.peers[server] = remote time.sleep(1)