public void Test() { // Arrange Election.CurrentTerm = 1; Election.VotedFor = Guid.NewGuid(); var message = new RequestVoteMessage(); RequestVote.Subscribe((m) => { message = m; }); // Act Candidate.RequestElection(); // Assert Assert.Equal(ServerIdentifier.Id, message.Candidate); Assert.Equal(Election.CurrentTerm, message.Term); }
public void VoteRequestReceived(RequestVoteMessage requestVote) { if (_serverIdentifier.Equals(requestVote.Candidate)) return; if (_options.UseLogging) _logger.LogInformation($"Processing {nameof(VoteRequestReceived)} \n\t\t Candidate {requestVote.Candidate} \n\t\t Term {requestVote.Term}"); if (!_nodes.Contains(requestVote.Candidate)) { _nodes.Add(requestVote.Candidate); } // If your a term ahead you won't vote for that old candidate if (requestVote.Term < _election.CurrentTerm) { _voteReply.OnNext(new RequestVoteResultMessage() { From = _serverIdentifier.Id, Candidate = _election.VotedFor, Term = _election.CurrentTerm, VoteGranted = false }); return; } // Your a term behind, you need to vote if (requestVote.Term > _election.CurrentTerm) { _election.CurrentTerm = requestVote.Term; // Do a check on the candidates log for completeness var isComplete = LogCompletness(requestVote); // Candidate looks good for being leader, vote for it if (isComplete) { _election.VotedFor = requestVote.Candidate; _voteReply.OnNext(new RequestVoteResultMessage() { From = _serverIdentifier, Candidate = _election.VotedFor, Term = _election.CurrentTerm, VoteGranted = true, }); _state?.OnNext(ServerStateType.Follower); } // We have detected a inconsistency in the candidate, so we must be a better candidate, votes for ourself else { _election.VotedFor = _serverIdentifier; _voteReply.OnNext(new RequestVoteResultMessage() { From = _serverIdentifier, Candidate = _election.VotedFor, Term = _election.CurrentTerm, VoteGranted = false }); _state?.OnNext(ServerStateType.Candidate); } return; } // You've already voted for this term _voteReply.OnNext(new RequestVoteResultMessage() { From = _serverIdentifier.Id, Candidate = _election.VotedFor, // send back who we voted for too make election more reliable to calculate the winner Term = _election.CurrentTerm, VoteGranted = _election.VotedFor == requestVote.Candidate }); }
// Grants candidate vote if its log is more up-to-date or equal than ours bool LogCompletness(RequestVoteMessage requestVote) { return requestVote.LastLogIndex >= _logReplication.LastApplied && requestVote.LastLogTerm >= _logReplication.LastTerm; }