public override void Handle(AppendEntriesResponse resp) { base.Handle(resp); var maxIndexOnQuorom = GetMaxIndexOnQuorum(); var lastLogEntry = Engine.PersistentState.LastLogEntry(); if (maxIndexOnQuorom >= lastLogEntry.Index) { _log.Info("Done sending all events to the cluster, can step down gracefully now"); TransferToBestMatch(); } }
private void PromoteNodeToVoter(AppendEntriesResponse resp) { // if we got a successful append entries response from a promotable node, and it has caught up // with the committed entries, it means that we can promote it to voting positions, since it // can now become a leader. var upgradedNode = Engine.CurrentTopology.GetNodeByName(resp.From); if (upgradedNode == null) return; var requestTopology = new Topology( Engine.CurrentTopology.TopologyId, Engine.CurrentTopology.AllVotingNodes.Union(new[] { upgradedNode }), Engine.CurrentTopology.NonVotingNodes, Engine.CurrentTopology.PromotableNodes.Where(x => x != upgradedNode) ); if (Engine.CurrentlyChangingTopology() == false) { _log.Info( "Node {0} is a promotable node, and it has caught up to the current cluster commit index, but we are currently updating the topology, will try again later", resp.From); return; } _log.Info( "Node {0} is a promotable node, and it has caught up to the current cluster commit index, promoting to voting member", resp.From); Engine.ModifyTopology(requestTopology); }
public override void Handle(AppendEntriesResponse resp) { if (FromOurTopology(resp) == false) { _log.Info("Got an append entries response message outside my cluster topology (id: {0}), ignoring", resp.ClusterTopologyId); return; } if (Engine.CurrentTopology.Contains(resp.From) == false) { _log.Info("Rejecting append entries response from {0} because it is not in my cluster", resp.From); return; } _log.Debug("Handling AppendEntriesResponse from {0}", resp.From); // there is a new leader in town, time to step down if (resp.CurrentTerm > Engine.PersistentState.CurrentTerm) { Engine.UpdateCurrentTerm(resp.CurrentTerm, resp.LeaderId); return; } Debug.Assert(resp.From != null); _nextIndexes[resp.From] = resp.LastLogIndex + 1; _matchIndexes[resp.From] = resp.LastLogIndex; _lastContact[resp.From] = DateTime.UtcNow; if (Engine.CurrentTopology.IsPromotable(resp.From) && resp.LastLogIndex == Engine.CommitIndex) { PromoteNodeToVoter(resp); } _log.Debug("Follower ({0}) has LastLogIndex = {1}", resp.From, resp.LastLogIndex); if (resp.Success == false) { _log.Debug("Received Success = false in AppendEntriesResponse from {1}. Now _nextIndexes[{1}] = {0}. Reason: {2}", _nextIndexes[resp.From], resp.From, resp.Message); return; } var maxIndexOnCurrentQuorum = GetMaxIndexOnQuorum(); if (maxIndexOnCurrentQuorum <= Engine.CommitIndex) { _log.Debug("maxIndexOnCurrentQuorum = {0} <= Engine.CommitIndex = {1}.", maxIndexOnCurrentQuorum, Engine.CommitIndex); return; } // we update the heartbeat time whenever we get a successful quorum, because // that means that we are good to run without any issues. Further handling is done // in the HandleTimeout, to handle a situation where the leader can't talk to the clients LastHeartbeatTime = DateTime.UtcNow; _log.Debug( "AppendEntriesResponse => applying commits, maxIndexOnQuorom = {0}, Engine.CommitIndex = {1}", maxIndexOnCurrentQuorum, Engine.CommitIndex); Engine.ApplyCommits(Engine.CommitIndex + 1, maxIndexOnCurrentQuorum, _pendingCommands.ToDictionary(x => x.AssignedIndex, x => x)); Command result; while (_pendingCommands.TryPeek(out result) && result.AssignedIndex <= maxIndexOnCurrentQuorum) { if (_pendingCommands.TryDequeue(out result) == false) break; // should never happen result.Complete(); } }
public override void Reply(AppendEntriesResponse resp) { Reply(resp.Success, resp); }
public void SendToSelf(AppendEntriesResponse resp) { Publish(resp, null); }
public void SendToSelf(AppendEntriesResponse resp) { _bus.SendToSelf(resp); }
public abstract void Reply(AppendEntriesResponse resp);
public virtual void Handle(AppendEntriesResponse resp) { // not a leader, no idea what to do with this. Probably an old // message from when we were a leader, ignoring. }