@@ -603,35 +603,38 @@ func (r *raft) maybeSendAppend(to uint64, sendIfEmpty bool) bool {
603
603
return false
604
604
}
605
605
606
- lastIndex , nextIndex := pr .Next - 1 , pr .Next
607
- lastTerm , errt := r .raftLog .term (lastIndex )
606
+ prevIndex := pr .Next - 1
607
+ prevTerm , err := r .raftLog .term (prevIndex )
608
+ if err != nil {
609
+ // The log probably got truncated at >= pr.Next, so we can't catch up the
610
+ // follower log anymore. Send a snapshot instead.
611
+ return r .maybeSendSnapshot (to , pr )
612
+ }
608
613
609
614
var ents []pb.Entry
610
- var erre error
611
615
// In a throttled StateReplicate only send empty MsgApp, to ensure progress.
612
616
// Otherwise, if we had a full Inflights and all inflight messages were in
613
617
// fact dropped, replication to that follower would stall. Instead, an empty
614
618
// MsgApp will eventually reach the follower (heartbeats responses prompt the
615
619
// leader to send an append), allowing it to be acked or rejected, both of
616
620
// which will clear out Inflights.
617
621
if pr .State != tracker .StateReplicate || ! pr .Inflights .Full () {
618
- ents , erre = r .raftLog .entries (nextIndex , r .maxMsgSize )
622
+ ents , err = r .raftLog .entries (pr . Next , r .maxMsgSize )
619
623
}
620
-
621
624
if len (ents ) == 0 && ! sendIfEmpty {
622
625
return false
623
626
}
624
-
625
- if errt != nil || erre != nil { // send snapshot if we failed to get term or entries
627
+ // TODO(pav-kv): move this check up to where err is returned.
628
+ if err != nil { // send a snapshot if we failed to get the entries
626
629
return r .maybeSendSnapshot (to , pr )
627
630
}
628
631
629
632
// Send the actual MsgApp otherwise, and update the progress accordingly.
630
633
r .send (pb.Message {
631
634
To : to ,
632
635
Type : pb .MsgApp ,
633
- Index : lastIndex ,
634
- LogTerm : lastTerm ,
636
+ Index : prevIndex ,
637
+ LogTerm : prevTerm ,
635
638
Entries : ents ,
636
639
Commit : r .raftLog .committed ,
637
640
})
0 commit comments