@@ -306,6 +306,7 @@ var (
306306 errEntryLoadFailed = errors .New ("raft: could not load entry from WAL" )
307307 errEntryStoreFailed = errors .New ("raft: could not store entry to WAL" )
308308 errNodeClosed = errors .New ("raft: node is closed" )
309+ errNodeRemoved = errors .New ("raft: peer was removed" )
309310 errBadSnapName = errors .New ("raft: snapshot name could not be parsed" )
310311 errNoSnapAvailable = errors .New ("raft: no snapshot available" )
311312 errCatchupsRunning = errors .New ("raft: snapshot can not be installed while catchups running" )
@@ -3147,8 +3148,19 @@ func (n *raft) applyCommit(index uint64) error {
31473148
31483149 n .commit = index
31493150 ae .buf = nil
3150-
31513151 var committed []* Entry
3152+
3153+ defer func () {
3154+ // Pass to the upper layers if we have normal entries. It is
3155+ // entirely possible that 'committed' might be an empty slice here,
3156+ // which will happen if we've processed updates inline (like peer
3157+ // states). In which case the upper layer will just call down with
3158+ // Applied() with no further action.
3159+ n .apply .push (newCommittedEntry (index , committed ))
3160+ // Place back in the pool.
3161+ ae .returnToPool ()
3162+ }()
3163+
31523164 for _ , e := range ae .entries {
31533165 switch e .Type {
31543166 case EntryNormal :
@@ -3199,6 +3211,9 @@ func (n *raft) applyCommit(index uint64) error {
31993211 // We pass these up as well.
32003212 committed = append (committed , e )
32013213
3214+ // We are done with this membership change
3215+ n .membChanging = false
3216+
32023217 case EntryRemovePeer :
32033218 peer := string (e .Data )
32043219 n .debug ("Removing peer %q" , peer )
@@ -3217,29 +3232,22 @@ func (n *raft) applyCommit(index uint64) error {
32173232 n .writePeerState (& peerState {n .peerNames (), n .csz , n .extSt })
32183233 }
32193234
3220- // If this is us and we are the leader we should attempt to stepdown.
3221- if peer == n .id && n .State () == Leader {
3222- n .stepdownLocked (n .selectNextLeader ())
3223- }
3224-
32253235 // Remove from string intern map.
32263236 peers .Delete (peer )
32273237
32283238 // We pass these up as well.
32293239 committed = append (committed , e )
3230- }
3231- if e . ChangesMembership () {
3240+
3241+ // We are done with this membership change
32323242 n .membChanging = false
3243+
3244+ // If this is us and we are the leader signal the caller
3245+ // to attempt to stepdown.
3246+ if peer == n .id && n .State () == Leader {
3247+ return errNodeRemoved
3248+ }
32333249 }
32343250 }
3235- // Pass to the upper layers if we have normal entries. It is
3236- // entirely possible that 'committed' might be an empty slice here,
3237- // which will happen if we've processed updates inline (like peer
3238- // states). In which case the upper layer will just call down with
3239- // Applied() with no further action.
3240- n .apply .push (newCommittedEntry (index , committed ))
3241- // Place back in the pool.
3242- ae .returnToPool ()
32433251 return nil
32443252}
32453253
@@ -3291,19 +3299,36 @@ func (n *raft) trackResponse(ar *appendEntryResponse) {
32913299 }
32923300 results [ar .peer ] = struct {}{}
32933301
3294- // We don't count ourselves to account for leader changes, so add 1.
3295- if nr := len (results ); nr + 1 >= n .qn {
3302+ acks := len (results )
3303+ if n .peers [n .ID ()] != nil {
3304+ // Count the leader if it's still part of membership
3305+ acks += 1
3306+ }
3307+
3308+ var applyErr error
3309+ if acks >= n .qn {
32963310 // We have a quorum.
32973311 for index := n .commit + 1 ; index <= ar .index ; index ++ {
3298- if err := n .applyCommit (index ); err != nil && err != errNodeClosed {
3299- n .error ("Got an error applying commit for %d: %v" , index , err )
3312+ if applyErr = n .applyCommit (index ); applyErr != nil {
3313+ switch applyErr {
3314+ case errNodeClosed , errNodeRemoved :
3315+ default :
3316+ n .error ("Got an error applying commit for %d: %v" , index , applyErr )
3317+ }
33003318 break
33013319 }
33023320 }
33033321 sendHB = n .prop .len () == 0
33043322 }
33053323 n .Unlock ()
33063324
3325+ if applyErr == errNodeRemoved {
3326+ // Leader was peer-removed. Attempt a step-down to
3327+ // a new leader before shutting down.
3328+ n .StepDown ()
3329+ n .Stop ()
3330+ }
3331+
33073332 if sendHB {
33083333 n .sendHeartbeat ()
33093334 }
0 commit comments