This is an automated email from the ASF dual-hosted git repository.

AlexStocks pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/develop by this push:
     new 672933f02 fix(dubbo): accept bare-ms timeout attachment so failover 
retries keep the configured timeout (#3714)
672933f02 is described below

commit 672933f0270675182a71925ff546a8f7cc4da239
Author: eye-gu <[email protected]>
AuthorDate: Sun Aug 30 03:45:59 2026 +0800

    fix(dubbo): accept bare-ms timeout attachment so failover retries keep the 
configured timeout (#3714)
    
    * fix(dubbo): accept bare-ms timeout attachment so failover retries keep 
the configured timeout
    
    * fix(dubbo): guard bare-ms timeout attachment against time.Duration 
overflow
---
 protocol/dubbo/dubbo_invoker.go      |  6 +++++-
 protocol/dubbo/dubbo_invoker_test.go | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/protocol/dubbo/dubbo_invoker.go b/protocol/dubbo/dubbo_invoker.go
index 9f444b320..8ce642076 100644
--- a/protocol/dubbo/dubbo_invoker.go
+++ b/protocol/dubbo/dubbo_invoker.go
@@ -163,7 +163,11 @@ func (di *DubboInvoker) Invoke(ctx context.Context, ivc 
base.Invocation) result.
 func (di *DubboInvoker) getTimeout(ivc *invocation.RPCInvocation) 
time.Duration {
        timeout := di.timeout                                                
//default timeout
        if attachTimeout, ok := ivc.GetAttachment(constant.TimeoutKey); ok { 
//check invocation timeout
-               timeout, _ = time.ParseDuration(attachTimeout)
+               if d, err := time.ParseDuration(attachTimeout); err == nil {
+                       timeout = d
+               } else if d, err := time.ParseDuration(attachTimeout + "ms"); 
err == nil {
+                       timeout = d
+               }
        } else { // check method timeout
                methodName := ivc.MethodName()
                if di.GetURL().GetParamBool(constant.GenericKey, false) {
diff --git a/protocol/dubbo/dubbo_invoker_test.go 
b/protocol/dubbo/dubbo_invoker_test.go
index e0fe4d983..47124706b 100644
--- a/protocol/dubbo/dubbo_invoker_test.go
+++ b/protocol/dubbo/dubbo_invoker_test.go
@@ -18,6 +18,8 @@
 package dubbo
 
 import (
+       "math"
+       "strconv"
        "testing"
        "time"
 )
@@ -31,6 +33,7 @@ import (
        "dubbo.apache.org/dubbo-go/v3/common"
        "dubbo.apache.org/dubbo-go/v3/common/constant"
        "dubbo.apache.org/dubbo-go/v3/global"
+       "dubbo.apache.org/dubbo-go/v3/protocol/invocation"
 )
 
 func TestNewDubboInvokerUsesGlobalDefaultTimeout(t *testing.T) {
@@ -63,6 +66,37 @@ func TestNewDubboInvokerUsesTimeoutParam(t *testing.T) {
        assert.Equal(t, 5*time.Second, invoker.timeout)
 }
 
+func TestGetTimeoutAcrossAttemptsOnSameInvocation(t *testing.T) {
+       url, err := 
common.NewURL("dubbo://127.0.0.1:20880/org.apache.dubbo.UserProvider?timeout=10s")
+       require.NoError(t, err)
+
+       invoker := NewDubboInvoker(url, nil)
+       inv := invocation.NewRPCInvocation("GetUser", nil, nil)
+
+       // the first attempt writes the timeout back as bare milliseconds;
+       // retries on the same invocation (failover) must resolve the same 
timeout
+       assert.Equal(t, 10*time.Second, invoker.getTimeout(inv))
+       assert.Equal(t, 10*time.Second, invoker.getTimeout(inv))
+}
+
+func TestGetTimeoutBareMsOverflowBoundary(t *testing.T) {
+       url, err := 
common.NewURL("dubbo://127.0.0.1:20880/org.apache.dubbo.UserProvider?timeout=10s")
+       require.NoError(t, err)
+
+       invoker := NewDubboInvoker(url, nil)
+
+       // the largest whole milliseconds time.Duration can represent 
(9223372036854)
+       maxMs := math.MaxInt64 / int64(time.Millisecond)
+       inv := invocation.NewRPCInvocation("GetUser", nil, nil)
+       inv.SetAttachment(constant.TimeoutKey, strconv.FormatInt(maxMs, 10))
+       assert.Equal(t, time.Duration(maxMs)*time.Millisecond, 
invoker.getTimeout(inv))
+
+       // one more millisecond would overflow into a negative duration; keep 
the default
+       inv = invocation.NewRPCInvocation("GetUser", nil, nil)
+       inv.SetAttachment(constant.TimeoutKey, strconv.FormatInt(maxMs+1, 10))
+       assert.Equal(t, 10*time.Second, invoker.getTimeout(inv))
+}
+
 //
 //import (
 //     "bytes"

Reply via email to