Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
2b67f5256a | |||
6aa8b631e6 | |||
72dea51e6a | |||
74fa0270a4 |
@ -342,7 +342,9 @@ func (c *httpClusterClient) Do(ctx context.Context, act httpAction) (*http.Respo
|
|||||||
resp, body, err = hc.Do(ctx, action)
|
resp, body, err = hc.Do(ctx, action)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cerr.Errors = append(cerr.Errors, err)
|
cerr.Errors = append(cerr.Errors, err)
|
||||||
// mask previous errors with context error, which is controlled by user
|
if err == ctx.Err() {
|
||||||
|
return nil, nil, ctx.Err()
|
||||||
|
}
|
||||||
if err == context.Canceled || err == context.DeadlineExceeded {
|
if err == context.Canceled || err == context.DeadlineExceeded {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -295,7 +295,7 @@ func TestSimpleHTTPClientDoHeaderTimeout(t *testing.T) {
|
|||||||
t.Fatalf("expected non-nil error, got nil")
|
t.Fatalf("expected non-nil error, got nil")
|
||||||
}
|
}
|
||||||
case <-time.After(time.Second):
|
case <-time.After(time.Second):
|
||||||
t.Fatalf("unexpected timeout when waitting for the test to finish")
|
t.Fatalf("unexpected timeout when waiting for the test to finish")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,7 +444,51 @@ func TestHTTPClusterClientDoDeadlineExceedContext(t *testing.T) {
|
|||||||
t.Errorf("err = %+v, want %+v", err, context.DeadlineExceeded)
|
t.Errorf("err = %+v, want %+v", err, context.DeadlineExceeded)
|
||||||
}
|
}
|
||||||
case <-time.After(time.Second):
|
case <-time.After(time.Second):
|
||||||
t.Fatalf("unexpected timeout when waitting for request to deadline exceed")
|
t.Fatalf("unexpected timeout when waiting for request to deadline exceed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeCancelContext struct{}
|
||||||
|
|
||||||
|
var fakeCancelContextError = errors.New("fake context canceled")
|
||||||
|
|
||||||
|
func (f fakeCancelContext) Deadline() (time.Time, bool) { return time.Time{}, false }
|
||||||
|
func (f fakeCancelContext) Done() <-chan struct{} {
|
||||||
|
d := make(chan struct{}, 1)
|
||||||
|
d <- struct{}{}
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
func (f fakeCancelContext) Err() error { return fakeCancelContextError }
|
||||||
|
func (f fakeCancelContext) Value(key interface{}) interface{} { return 1 }
|
||||||
|
|
||||||
|
func withTimeout(parent context.Context, timeout time.Duration) (context.Context, context.CancelFunc) {
|
||||||
|
return parent, func() { parent = nil }
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHTTPClusterClientDoCanceledContext(t *testing.T) {
|
||||||
|
fakeURL := url.URL{}
|
||||||
|
tr := newFakeTransport()
|
||||||
|
tr.finishCancel <- struct{}{}
|
||||||
|
c := &httpClusterClient{
|
||||||
|
clientFactory: newHTTPClientFactory(tr, DefaultCheckRedirect, 0),
|
||||||
|
endpoints: []url.URL{fakeURL},
|
||||||
|
}
|
||||||
|
|
||||||
|
errc := make(chan error)
|
||||||
|
go func() {
|
||||||
|
ctx, cancel := withTimeout(fakeCancelContext{}, time.Millisecond)
|
||||||
|
cancel()
|
||||||
|
_, _, err := c.Do(ctx, &fakeAction{})
|
||||||
|
errc <- err
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case err := <-errc:
|
||||||
|
if err != fakeCancelContextError {
|
||||||
|
t.Errorf("err = %+v, want %+v", err, fakeCancelContextError)
|
||||||
|
}
|
||||||
|
case <-time.After(time.Second):
|
||||||
|
t.Fatalf("unexpected timeout when waiting for request to fake context canceled")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,11 +142,23 @@ func startPeer(transport *Transport, urls types.URLs, local, to, cid types.ID, r
|
|||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case mm := <-p.propc:
|
case mm := <-p.recvc:
|
||||||
if err := r.Process(ctx, mm); err != nil {
|
if err := r.Process(ctx, mm); err != nil {
|
||||||
plog.Warningf("failed to process raft message (%v)", err)
|
plog.Warningf("failed to process raft message (%v)", err)
|
||||||
}
|
}
|
||||||
case mm := <-p.recvc:
|
case <-p.stopc:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// r.Process might block for processing proposal when there is no leader.
|
||||||
|
// Thus propc must be put into a separate routine with recvc to avoid blocking
|
||||||
|
// processing other raft messages.
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case mm := <-p.propc:
|
||||||
if err := r.Process(ctx, mm); err != nil {
|
if err := r.Process(ctx, mm); err != nil {
|
||||||
plog.Warningf("failed to process raft message (%v)", err)
|
plog.Warningf("failed to process raft message (%v)", err)
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
// MinClusterVersion is the min cluster version this etcd binary is compatible with.
|
// MinClusterVersion is the min cluster version this etcd binary is compatible with.
|
||||||
MinClusterVersion = "2.2.0"
|
MinClusterVersion = "2.2.0"
|
||||||
Version = "2.3.0"
|
Version = "2.3.1"
|
||||||
|
|
||||||
// Git SHA Value will be set during build
|
// Git SHA Value will be set during build
|
||||||
GitSHA = "Not provided (use ./build instead of go build)"
|
GitSHA = "Not provided (use ./build instead of go build)"
|
||||||
|
Reference in New Issue
Block a user