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);

        }
Exemplo n.º 2
0
        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
            });
        }
Exemplo n.º 3
0
 // 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;
 }