func (d *Dinghy) AppendEntriesHandler() func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.Body != nil {
			defer r.Body.Close()
		}
		if r.Method != "POST" {
			d.logger.Errorf("invalid method %s", r.Method)
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}

		var ae AppendEntriesRequest
		if err := json.NewDecoder(r.Body).Decode(&ae); err != nil {
			d.logger.Errorf("%s", err)
			http.Error(w, emptyRequestVoteResponse.String(), http.StatusBadRequest)
			return
		}

		// There are a few cases here:
		// 1. The request is from an old term so reject
		// 2. The request is from a newer term so step down
		// 3. If we are a follower and get an append entries continue on with success
		// 4. If we are not a follower and get an append entries, it means there is
		//    another leader already and we should step down.
		switch {
		case ae.Term < d.State.Term():
			d.logger.Printf("got AppendEntries request from older term, rejecting %+v %s", ae, d.State)
			aeResp := appendEntriesResponse{
				Term:    d.State.Term(),
				Success: false,
				Reason:  fmt.Sprintf("term %d < %d", ae.Term, d.State.Term()),
			}
			if err := json.NewEncoder(w).Encode(aeResp); err != nil {
				http.Error(w, emptyRequestVoteResponse.String(), http.StatusInternalServerError)
			}
			return
		case ae.Term > d.State.Term():
			d.logger.Printf("got AppendEntries request from newer term, stepping down %+v %s", ae, d.State)
			d.State.StepDown(ae.Term)
		case ae.Term == d.State.Term():
			// ignore request to self and only step down if not in follower state.
			if ae.LeaderID != d.State.ID() && d.State.State() != StateFollower {
				d.logger.Printf("got AppendEntries request from another leader with the same term, stepping down %+v %s", ae, d.State)
				d.State.StepDown(ae.Term)
			}
		}

		// ok
		d.State.LeaderID(ae.LeaderID)
		d.State.AppendEntriesEvent(&ae)
		aeResp := appendEntriesResponse{
			Term:    d.State.Term(),
			Success: true,
		}
		if err := json.NewEncoder(w).Encode(aeResp); err != nil {
			http.Error(w, emptyRequestVoteResponse.String(), http.StatusInternalServerError)
		}
		return
	}
}
// AppendEntriesHandler (POST) handles append entry requests
AppendEntriesHandler (POST) handles append entry requests
// AppendEntriesHandler ( POST ) handles append entry requests
func (d *Dinghy) AppendEntriesHandler() func(w http.ResponseWriter, r *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		if r.Body != nil {
			defer r.Body.Close()
		}
		if r.Method != "POST" {
			d.logger.Errorf("invalid method %s", r.Method)
			http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
			return
		}
		var ae AppendEntriesRequest
		if err := json.NewDecoder(r.Body).Decode(&ae); err != nil {
			d.logger.Errorf("%s", err)
			http.Error(w, emptyRequestVoteResponse.String(), http.StatusBadRequest)
			return
		}
		switch {
		case ae.Term < d.State.Term():
			d.logger.Printf("got AppendEntries request from older term, rejecting %+v %s", ae, d.State)
			aeResp := appendEntriesResponse{
				Term:    d.State.Term(),
				Success: false,
				Reason:  fmt.Sprintf("term %d < %d", ae.Term, d.State.Term()),
			}
			if err := json.NewEncoder(w).Encode(aeResp); err != nil {
				http.Error(w, emptyRequestVoteResponse.String(), http.StatusInternalServerError)
			}
			return
		case ae.Term > d.State.Term():
			d.logger.Printf("got AppendEntries request from newer term, stepping down %+v %s", ae, d.State)
			d.State.StepDown(ae.Term)
		case ae.Term == d.State.Term():
			if ae.LeaderID != d.State.ID() && d.State.State() != StateFollower {
				d.logger.Printf("got AppendEntries request from another leader with the same term, stepping down %+v %s", ae, d.State)
				d.State.StepDown(ae.Term)
			}
		}
		d.State.LeaderID(ae.LeaderID)
		d.State.AppendEntriesEvent(&ae)
		aeResp := appendEntriesResponse{
			Term:    d.State.Term(),
			Success: true,
		}
		if err := json.NewEncoder(w).Encode(aeResp); err != nil {
			http.Error(w, emptyRequestVoteResponse.String(), http.StatusInternalServerError)
		}
		return
	}
}
func ( d * Dinghy ) AppendEntriesHandler ( ) func ( w http . ResponseWriter , r * http . Request ) { return func ( w http . ResponseWriter , r * http . Request ) { if r . Body != nil { defer r . Body . Close ( ) } if r . Method != " " { d . logger . Errorf ( " " , r . Method ) http . Error ( w , http . StatusText ( http . StatusMethodNotAllowed ) , http . StatusMethodNotAllowed ) return } var ae AppendEntriesRequest if err := json . NewDecoder ( r . Body ) . Decode ( & ae ) ; err != nil { d . logger . Errorf ( " " , err ) http . Error ( w , emptyRequestVoteResponse . String ( ) , http . StatusBadRequest ) return } switch { case ae . Term < d . State . Term ( ) : d . logger . Printf ( " " , ae , d . State ) aeResp := appendEntriesResponse { Term : d . State . Term ( ) , Success : false , Reason : fmt . Sprintf ( " " , ae . Term , d . State . Term ( ) ) , } if err := json . NewEncoder ( w ) . Encode ( aeResp ) ; err != nil { http . Error ( w , emptyRequestVoteResponse . String ( ) , http . StatusInternalServerError ) } return case ae . Term > d . State . Term ( ) : d . logger . Printf ( " " , ae , d . State ) d . State . StepDown ( ae . Term ) case ae . Term == d . State . Term ( ) : if ae . LeaderID != d . State . ID ( ) && d . State . State ( ) != StateFollower { d . logger . Printf ( " " , ae , d . State ) d . State . StepDown ( ae . Term ) } } d . State . LeaderID ( ae . LeaderID ) d . State . AppendEntriesEvent ( & ae ) aeResp := appendEntriesResponse { Term : d . State . Term ( ) , Success : true , } if err := json . NewEncoder ( w ) . Encode ( aeResp ) ; err != nil { http . Error ( w , emptyRequestVoteResponse . String ( ) , http . StatusInternalServerError ) } return } }
AppendEntriesHandler (POST) handles append entry requests
AppendEntriesHandler ( POST ) handles append entry requests
// There are a few cases here: // 1. The request is from an old term so reject // 2. The request is from a newer term so step down // 3. If we are a follower and get an append entries continue on with success // 4. If we are not a follower and get an append entries, it means there is //    another leader already and we should step down. // ignore request to self and only step down if not in follower state. // ok