Skip to content

Commit 813eb04

Browse files
committed
Use connectTimeoutMS for heartbeatTimeout
GODRIVER-726 Change-Id: I7041da51a9a056a149e1efc8a0baf8187e840d1a
1 parent 2e6bf7d commit 813eb04

File tree

5 files changed

+60
-1
lines changed

5 files changed

+60
-1
lines changed

x/mongo/driver/topology/server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ func (s *Server) heartbeat(conn connection.Connection) (description.Server, conn
370370
opts := []connection.Option{
371371
connection.WithConnectTimeout(func(time.Duration) time.Duration { return s.cfg.heartbeatTimeout }),
372372
connection.WithReadTimeout(func(time.Duration) time.Duration { return s.cfg.heartbeatTimeout }),
373+
connection.WithWriteTimeout(func(time.Duration) time.Duration { return s.cfg.heartbeatTimeout }),
373374
}
374375
opts = append(opts, s.cfg.connectionOpts...)
375376
// We override whatever handshaker is currently attached to the options with an empty

x/mongo/driver/topology/server_options.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ type serverConfig struct {
3232
func newServerConfig(opts ...ServerOption) (*serverConfig, error) {
3333
cfg := &serverConfig{
3434
heartbeatInterval: 10 * time.Second,
35-
heartbeatTimeout: 30 * time.Second,
35+
heartbeatTimeout: 10 * time.Second,
3636
maxConns: 100,
3737
maxIdleConns: 100,
3838
registry: defaultRegistry,

x/mongo/driver/topology/topology_options.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ func WithConnString(fn func(connstring.ConnString) connstring.ConnString) Option
7070
c.seedList = cs.Hosts
7171

7272
if cs.ConnectTimeout > 0 {
73+
c.serverOpts = append(c.serverOpts, WithHeartbeatTimeout(func(time.Duration) time.Duration { return cs.ConnectTimeout }))
7374
connOpts = append(connOpts, connection.WithConnectTimeout(func(time.Duration) time.Duration { return cs.ConnectTimeout }))
7475
}
7576

x/network/integration/main_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,3 +160,25 @@ func (d *dialer) lenclosed() int {
160160
defer d.Unlock()
161161
return len(d.closed)
162162
}
163+
164+
// bootstrapConnections lists for num connections on the returned address. The user provided run
165+
// function will be called with the accepted connection. The user is responsible for closing the
166+
// connection.
167+
func bootstrapConnections(t *testing.T, num int, run func(net.Conn)) net.Addr {
168+
l, err := net.Listen("tcp", "localhost:0")
169+
if err != nil {
170+
t.Errorf("Could not set up a listener: %v", err)
171+
t.FailNow()
172+
}
173+
go func() {
174+
for i := 0; i < num; i++ {
175+
c, err := l.Accept()
176+
if err != nil {
177+
t.Errorf("Could not accept a connection: %v", err)
178+
}
179+
go run(c)
180+
}
181+
_ = l.Close()
182+
}()
183+
return l.Addr()
184+
}

x/network/integration/topology_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"context"
1111
"net"
1212
"testing"
13+
"time"
1314

1415
"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
1516
"github.com/mongodb/mongo-go-driver/x/network/connection"
@@ -85,6 +86,40 @@ func TestTopologyTopology(t *testing.T) {
8586
d.lenclosed(), d.lenopened())
8687
}
8788
})
89+
t.Run("can disconnect from hung server", func(t *testing.T) {
90+
bctx, cancel := context.WithCancel(context.Background())
91+
defer cancel()
92+
start := make(chan struct{}, 1)
93+
addr := bootstrapConnections(t, 5, func(_ net.Conn) {
94+
start <- struct{}{}
95+
<-bctx.Done()
96+
})
97+
topo, err := topology.New(
98+
topology.WithConnString(
99+
func(connstring.ConnString) connstring.ConnString {
100+
cs, err := connstring.Parse("mongodb://" + addr.String() + "/")
101+
noerr(t, err)
102+
cs.ConnectTimeout = 20 * time.Millisecond
103+
return cs
104+
},
105+
),
106+
)
107+
noerr(t, err)
108+
err = topo.Connect(context.TODO())
109+
noerr(t, err)
110+
<-start
111+
done := make(chan struct{}, 1)
112+
go func() {
113+
err := topo.Disconnect(bctx)
114+
noerr(t, err)
115+
done <- struct{}{}
116+
}()
117+
select {
118+
case <-done:
119+
case <-time.After(300 * time.Millisecond):
120+
t.Error("Could not disconnect a topology within required timelimit")
121+
}
122+
})
88123
})
89124
t.Run("Connect", func(t *testing.T) {
90125
t.Run("can reconnect a disconnected topology", func(t *testing.T) {

0 commit comments

Comments
 (0)