From 138f356c5d19b2d18e2f326a390b49734bc4965b Mon Sep 17 00:00:00 2001 From: chrislusf Date: Wed, 28 Oct 2026 00:42:06 -0700 Subject: [PATCH] wdclient: cover a lapsed caller deadline that Err() has not observed yet --- weed/wdclient/filer_client.go | 3 ++- weed/wdclient/filer_client_test.go | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/weed/wdclient/filer_client.go b/weed/wdclient/filer_client.go index 98f1150144..4a2802d484 100644 --- a/weed/wdclient/filer_client.go +++ b/weed/wdclient/filer_client.go @@ -2,6 +2,7 @@ package wdclient import ( "context" + "errors" "fmt" "math/rand" "strings" @@ -792,7 +793,7 @@ func (p *filerVolumeProvider) LookupVolumeIds(ctx context.Context, volumeIds []s // surface its own DeadlineExceeded a tick before ctx.Err() // becomes visible, so reinterpret only deadline errors this way ctxErr := ctx.Err() - if ctxErr == nil && status.Code(err) == codes.DeadlineExceeded { + if ctxErr == nil && (errors.Is(err, context.DeadlineExceeded) || status.Code(err) == codes.DeadlineExceeded) { if dl, ok := ctx.Deadline(); ok && !dl.After(time.Now()) { ctxErr = context.DeadlineExceeded } diff --git a/weed/wdclient/filer_client_test.go b/weed/wdclient/filer_client_test.go index f1ccc59ec4..1bfa56223f 100644 --- a/weed/wdclient/filer_client_test.go +++ b/weed/wdclient/filer_client_test.go @@ -309,6 +309,14 @@ func startStallingFiler(t *testing.T) pb.ServerAddress { return pb.ServerAddress(fmt.Sprintf("127.0.0.1:0.%s", port)) } +// lapsedDeadlineCtx mimics the moment after a caller's deadline has passed but +// before the runtime marks the context done. +type lapsedDeadlineCtx struct{ context.Context } + +func (lapsedDeadlineCtx) Deadline() (time.Time, bool) { return time.Now().Add(-time.Second), true } +func (lapsedDeadlineCtx) Done() <-chan struct{} { return nil } +func (lapsedDeadlineCtx) Err() error { return nil } + // A caller giving up must not count as a filer failure, the filer's own timeout must. func TestLookupVolumeIdsCountsOnlyFilerFailures(t *testing.T) { tests := []struct { @@ -338,6 +346,15 @@ func TestLookupVolumeIdsCountsOnlyFilerFailures(t *testing.T) { wantErr: context.DeadlineExceeded, wantFailures: 0, }, + { + name: "caller deadline already elapsed", + callerCtx: func() (context.Context, context.CancelFunc) { + return lapsedDeadlineCtx{context.Background()}, func() {} + }, + grpcTimeout: 5 * time.Second, + wantErr: context.DeadlineExceeded, + wantFailures: 0, + }, { name: "filer timeout", callerCtx: func() (context.Context, context.CancelFunc) {