Merge pull request #3759 from yichengq/rafthttp-unreachable

rafthttp: mark unreachable on unexpected response
This commit is contained in:
Yicheng Qin 2015-10-29 15:12:23 -07:00
commit 1b3d9130c9
3 changed files with 15 additions and 6 deletions

View File

@ -153,14 +153,17 @@ func (p *pipeline) post(data []byte) (err error) {
resp.Body.Close() resp.Body.Close()
err = checkPostResponse(resp, b, req, p.to) err = checkPostResponse(resp, b, req, p.to)
// errMemberRemoved is a critical error since a removed member should if err != nil {
// always be stopped. So we use reportCriticalError to report it to errorc. p.picker.unreachable(u)
if err == errMemberRemoved { // errMemberRemoved is a critical error since a removed member should
reportCriticalError(err, p.errorc) // always be stopped. So we use reportCriticalError to report it to errorc.
return nil if err == errMemberRemoved {
reportCriticalError(err, p.errorc)
}
return err
} }
return err return nil
} }
// waitSchedule waits other goroutines to be scheduled for a while // waitSchedule waits other goroutines to be scheduled for a while

View File

@ -392,12 +392,14 @@ func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) {
lv := semver.Must(semver.NewVersion(version.Version)) lv := semver.Must(semver.NewVersion(version.Version))
if compareMajorMinorVersion(rv, lv) == -1 && !checkStreamSupport(rv, t) { if compareMajorMinorVersion(rv, lv) == -1 && !checkStreamSupport(rv, t) {
resp.Body.Close() resp.Body.Close()
cr.picker.unreachable(u)
return nil, errUnsupportedStreamType return nil, errUnsupportedStreamType
} }
switch resp.StatusCode { switch resp.StatusCode {
case http.StatusGone: case http.StatusGone:
resp.Body.Close() resp.Body.Close()
cr.picker.unreachable(u)
err := fmt.Errorf("the member has been permanently removed from the cluster") err := fmt.Errorf("the member has been permanently removed from the cluster")
select { select {
case cr.errorc <- err: case cr.errorc <- err:
@ -408,6 +410,7 @@ func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) {
return resp.Body, nil return resp.Body, nil
case http.StatusNotFound: case http.StatusNotFound:
resp.Body.Close() resp.Body.Close()
cr.picker.unreachable(u)
return nil, fmt.Errorf("remote member %s could not recognize local member", cr.remote) return nil, fmt.Errorf("remote member %s could not recognize local member", cr.remote)
case http.StatusPreconditionFailed: case http.StatusPreconditionFailed:
b, err := ioutil.ReadAll(resp.Body) b, err := ioutil.ReadAll(resp.Body)
@ -416,6 +419,7 @@ func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) {
return nil, err return nil, err
} }
resp.Body.Close() resp.Body.Close()
cr.picker.unreachable(u)
switch strings.TrimSuffix(string(b), "\n") { switch strings.TrimSuffix(string(b), "\n") {
case errIncompatibleVersion.Error(): case errIncompatibleVersion.Error():
@ -430,6 +434,7 @@ func (cr *streamReader) dial(t streamType) (io.ReadCloser, error) {
} }
default: default:
resp.Body.Close() resp.Body.Close()
cr.picker.unreachable(u)
return nil, fmt.Errorf("unhandled http status %d", resp.StatusCode) return nil, fmt.Errorf("unhandled http status %d", resp.StatusCode)
} }
} }

View File

@ -128,6 +128,7 @@ func TestTransportUpdate(t *testing.T) {
func TestTransportErrorc(t *testing.T) { func TestTransportErrorc(t *testing.T) {
errorc := make(chan error, 1) errorc := make(chan error, 1)
tr := &Transport{ tr := &Transport{
Raft: &fakeRaft{},
LeaderStats: stats.NewLeaderStats(""), LeaderStats: stats.NewLeaderStats(""),
ErrorC: errorc, ErrorC: errorc,
streamRt: newRespRoundTripper(http.StatusForbidden, nil), streamRt: newRespRoundTripper(http.StatusForbidden, nil),