shangxinxiaolin opened a new issue, #3756:
URL: https://github.com/apache/dubbo-go/issues/3756

   # [Bug]: Reference request timeout is overwritten by the consumer default
   
   ### What happened?
   
   An explicit reference-level `WithRequestTimeout(500 * time.Millisecond)` is 
overwritten by the consumer-level default `3s` when `ReferenceOptions.refer()` 
builds the reference URL.
   
   Expected: the constructed reference URL has `timeout=500ms`.
   
   Actual: it has `timeout=3s`.
   
   I reproduced the URL construction behavior with a mock protocol and cluster, 
invoking the actual `ReferenceOptions.Refer()` path. This reproduction does not 
make a network RPC or measure end-to-end call duration.
   
   Root cause:
   
   - 
[`getURLMap()`](https://github.com/apache/dubbo-go/blob/832124aaacf0283445d379e935ff5d73695fa84d/client/action.go#L415-L417)
 sets the reference timeout.
   - 
[`refer()`](https://github.com/apache/dubbo-go/blob/832124aaacf0283445d379e935ff5d73695fa84d/client/action.go#L129-L138)
 first applies `WithParams(refOpts.getURLMap())`, then unconditionally 
overwrites the timeout with `refOpts.Consumer.RequestTimeout`.
   - The Triple client [reads the resulting URL 
timeout](https://github.com/apache/dubbo-go/blob/832124aaacf0283445d379e935ff5d73695fa84d/protocol/triple/client.go#L132-L134)
 as its default call timeout.
   
   Possible fix: use the consumer-level timeout only as a fallback when the 
reference-level timeout is empty, preserving an explicitly configured reference 
timeout.
   
   ### How can we reproduce it?
   
   Add the following file as `client/timeout_issue_repro_test.go`:
   
   ```go
   package client
   
   import (
       "testing"
       "time"
   
       "dubbo.apache.org/dubbo-go/v3/cluster/cluster"
       "dubbo.apache.org/dubbo-go/v3/cluster/directory"
       "dubbo.apache.org/dubbo-go/v3/common"
       "dubbo.apache.org/dubbo-go/v3/common/constant"
       "dubbo.apache.org/dubbo-go/v3/common/extension"
       "dubbo.apache.org/dubbo-go/v3/global"
       "dubbo.apache.org/dubbo-go/v3/protocol/base"
   )
   
   type timeoutIssueProtocol struct{ captured *common.URL }
   
   func (p *timeoutIssueProtocol) Export(base.Invoker) base.Exporter { return 
nil }
   func (p *timeoutIssueProtocol) Destroy() {}
   func (p *timeoutIssueProtocol) Refer(u *common.URL) base.Invoker {
       p.captured = u
       return base.NewBaseInvoker(u)
   }
   
   type timeoutIssueCluster struct{}
   
   func (timeoutIssueCluster) Join(d directory.Directory) base.Invoker {
       return base.NewBaseInvoker(d.GetURL())
   }
   
   func TestIssueReferenceTimeoutPrecedence(t *testing.T) {
       p := &timeoutIssueProtocol{}
       extension.SetProtocol("timeout-issue-repro", func() base.Protocol { 
return p })
       extension.SetCluster("timeout-issue-repro", func() cluster.Cluster { 
return timeoutIssueCluster{} })
   
       opts := defaultReferenceOptions()
       opts.Consumer = global.DefaultConsumerConfig()
       opts.Consumer.RequestTimeout = "3s"
       WithRequestTimeout(500 * time.Millisecond)(opts)
       opts.Reference.InterfaceName = "example.TimeoutService"
       opts.Reference.Protocol = "timeout-issue-repro"
       opts.Reference.Cluster = "timeout-issue-repro"
       opts.Reference.URL = "timeout-issue-repro://127.0.0.1:20000"
       opts.Reference.Filter = "-default"
       opts.Refer()
   
       if p.captured == nil {
           t.Fatal("Refer did not capture a URL")
       }
       actual := p.captured.GetParam(constant.TimeoutKey, "")
       t.Logf("consumer=%s reference=%s effective=%s", 
opts.Consumer.RequestTimeout, opts.Reference.RequestTimeout, actual)
       if actual != "500ms" {
           t.Fatalf("expected reference timeout 500ms, got %s", actual)
       }
   }
   ```
   
   Run:
   
   ```sh
   go test ./client -run '^TestIssueReferenceTimeoutPrecedence$' -count=1 -v
   ```
   
   Relevant output:
   
   ```text
   === RUN   TestIssueReferenceTimeoutPrecedence
       timeout_issue_repro_test.go:51: consumer=3s reference=500ms effective=3s
       timeout_issue_repro_test.go:53: expected reference timeout 500ms, got 3s
   --- FAIL: TestIssueReferenceTimeoutPrecedence (0.01s)
   FAIL
   ```
   
   ### Environment
   
   - Dubbo-Go: Apache `main`, commit `832124aaacf0283445d379e935ff5d73695fa84d` 
(the local fork HEAD matches the upstream main HEAD checked during 
investigation)
   - Go: `go1.25.5 windows/amd64`
   - OS: Windows
   - Consumer timeout: `3s`
   - Reference timeout: `500ms`
   - Reproduction uses mock transport and cluster extensions; no registry or 
external server is required.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to