private void BecomeLeader() { lock (_lock) { CancelScheduledEvents(); _state = RaftServerState.Leader; _auditLog.LogRecord(new AuditRecord(AuditRecordType.BecomeLeader, Id, _state, _currentTerm)); Task.Run(SendHeartbeat); } }
public AuditRecord(AuditRecordType type, string candidate, RaftServerState state, int term, string extraInfo = "") { When = DateTime.Now; Type = type; Id = candidate; Term = term; ExtraInfo = extraInfo; State = state; Log.Write(GetLogEventLevel(type), "Raft audit: {@item}", this); }
public Task BecomeFollower(int term) { lock (_lock) { CancelScheduledEvents(); UpdateTerm(term); //Become follower can be called when we already are one (e.g. on receipt of a heartbeat) if (_state != RaftServerState.Follower) { _state = RaftServerState.Follower; _auditLog.LogRecord(new AuditRecord(AuditRecordType.BecomeFollower, Id, _state, _currentTerm)); } return(Task.Run(ScheduleFollowerTimeout)); } }
public async Task BecomeCandidate() { _state = RaftServerState.Candidate; _auditLog.LogRecord(new AuditRecord(AuditRecordType.BecomeCandidate, Id, _state, _currentTerm)); while (_state == RaftServerState.Candidate) { lock (_lock) { CancelScheduledEvents(); _currentTerm++; _votesReceived = 0; _votedFor = null; _auditLog.LogRecord(new AuditRecord(AuditRecordType.StartElection, Id, _state, _currentTerm)); //vote for self ReceiveVote( new RequestVoteResult { Term = _currentTerm, VoteGranted = true, VoterId = Id, } ); _votedFor = Id; var token = _taskCancellation.Token; //TODO error handling, cancellation var pendingRequests = new List <Task>( _servers.Select( s => RequestAndReceiveVote(s, token) ) ); } //wait timeout period await _planner.ElectionDelay(); //if we are still in candidate state, run another election //no need to cancel inflight vote requests because increment to term means they will be ignored } }