Skip to content

Commit 892848a

Browse files
committed
GODRIVER-2218 Bump connection idle deadline on pool checkIn.
1 parent a2b9ada commit 892848a

File tree

4 files changed

+73
-38
lines changed

4 files changed

+73
-38
lines changed

x/mongo/driver/topology/cmap_prose_test.go

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -186,40 +186,6 @@ func TestCMAPProse(t *testing.T) {
186186
assert.Equal(t, event.ReasonConnectionErrored, evt.Reason, "expected reason %q, got %q",
187187
event.ReasonConnectionErrored, evt.Reason)
188188
})
189-
t.Run("expired connection", func(t *testing.T) {
190-
// If the connection being returned to the pool is expired, it should be removed from the pool and an
191-
// event should be published.
192-
clearEvents()
193-
194-
var dialer DialerFunc = func(context.Context, string, string) (net.Conn, error) {
195-
return &testNetConn{}, nil
196-
}
197-
198-
// We don't use the WithHandshaker option so the connection won't error during handshaking.
199-
// WithIdleTimeout must be used because the connection.idleTimeoutExpired() function only checks the
200-
// deadline if the idleTimeout option is greater than 0.
201-
connOpts := []ConnectionOption{
202-
WithDialer(func(Dialer) Dialer { return dialer }),
203-
WithIdleTimeout(func(time.Duration) time.Duration { return 1 * time.Second }),
204-
}
205-
pool := createTestPool(t, getConfig(), connOpts...)
206-
defer pool.close(context.Background())
207-
208-
conn, err := pool.checkOut(context.Background())
209-
assert.Nil(t, err, "checkOut() error: %v", err)
210-
211-
// Set the idleDeadline to a time in the past to simulate expiration.
212-
pastTime := time.Now().Add(-10 * time.Second)
213-
conn.idleDeadline.Store(pastTime)
214-
215-
err = pool.checkIn(conn)
216-
assert.Nil(t, err, "checkIn() error: %v", err)
217-
218-
assertConnectionCounts(t, pool, 1, 1)
219-
evt := <-closed
220-
assert.Equal(t, event.ReasonIdle, evt.Reason, "expected reason %q, got %q",
221-
event.ReasonIdle, evt.Reason)
222-
})
223189
})
224190
t.Run("close", func(t *testing.T) {
225191
t.Run("connections returned gracefully", func(t *testing.T) {

x/mongo/driver/topology/connection.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,6 @@ func (c *connection) connect(ctx context.Context) (err error) {
201201
c.nc = tlsNc
202202
}
203203

204-
c.bumpIdleDeadline()
205-
206204
// running hello and authentication is handled by a handshaker on the configuration instance.
207205
handshaker := c.config.handshaker
208206
if handshaker == nil {
@@ -357,7 +355,6 @@ func (c *connection) writeWireMessage(ctx context.Context, wm []byte) error {
357355
}
358356
}
359357

360-
c.bumpIdleDeadline()
361358
return nil
362359
}
363360

@@ -422,7 +419,6 @@ func (c *connection) readWireMessage(ctx context.Context, dst []byte) ([]byte, e
422419
}
423420
}
424421

425-
c.bumpIdleDeadline()
426422
return dst, nil
427423
}
428424

x/mongo/driver/topology/pool.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,8 @@ func (p *pool) checkInNoEvent(conn *connection) error {
596596
return ErrWrongPool
597597
}
598598

599+
conn.bumpIdleDeadline()
600+
599601
if reason, perished := connectionPerished(conn); perished {
600602
_ = p.removeConnection(conn, reason)
601603
go func() {

x/mongo/driver/topology/pool_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,77 @@ func TestPool(t *testing.T) {
840840
p1.close(context.Background())
841841
p2.close(context.Background())
842842
})
843+
t.Run("bumps the connection idle deadline", func(t *testing.T) {
844+
t.Parallel()
845+
846+
cleanup := make(chan struct{})
847+
defer close(cleanup)
848+
addr := bootstrapConnections(t, 1, func(nc net.Conn) {
849+
<-cleanup
850+
_ = nc.Close()
851+
})
852+
853+
d := newdialer(&net.Dialer{})
854+
p := newPool(poolConfig{
855+
Address: address.Address(addr.String()),
856+
MaxIdleTime: 1 * time.Millisecond,
857+
}, WithDialer(func(Dialer) Dialer { return d }))
858+
err := p.ready()
859+
noerr(t, err)
860+
861+
c, err := p.checkOut(context.Background())
862+
noerr(t, err)
863+
864+
// Sleep for 10ms, which will exceed the 1ms connection idle timeout. Then check the
865+
// connection back in and expect that it is not closed because checkIn() should bump the
866+
// connection idle deadline.
867+
time.Sleep(10 * time.Millisecond)
868+
err = p.checkIn(c)
869+
noerr(t, err)
870+
871+
assert.Equalf(t, 0, d.lenclosed(), "should have closed 0 connections")
872+
assert.Equalf(t, 1, p.availableConnectionCount(), "should have 1 idle connections in pool")
873+
assert.Equalf(t, 1, p.totalConnectionCount(), "should have 1 total connection in pool")
874+
875+
p.close(context.Background())
876+
})
877+
t.Run("sets minPoolSize connection idle deadline", func(t *testing.T) {
878+
t.Parallel()
879+
880+
cleanup := make(chan struct{})
881+
defer close(cleanup)
882+
addr := bootstrapConnections(t, 4, func(nc net.Conn) {
883+
<-cleanup
884+
_ = nc.Close()
885+
})
886+
887+
d := newdialer(&net.Dialer{})
888+
p := newPool(poolConfig{
889+
Address: address.Address(addr.String()),
890+
MinPoolSize: 3,
891+
MaxIdleTime: 10 * time.Millisecond,
892+
}, WithDialer(func(Dialer) Dialer { return d }))
893+
err := p.ready()
894+
noerr(t, err)
895+
896+
// Wait for maintain() to open 3 connections.
897+
assertConnectionsOpened(t, d, 3)
898+
899+
// Sleep for 100ms, which will exceed the 10ms connection idle timeout, then try to check
900+
// out a connection. Expect that all minPoolSize connections checked into the pool by
901+
// maintain() have passed their idle deadline, so checkOut() close all 3 connections and
902+
// try to create a new connection.
903+
time.Sleep(100 * time.Millisecond)
904+
_, err = p.checkOut(context.Background())
905+
noerr(t, err)
906+
907+
assertConnectionsClosed(t, d, 3)
908+
assert.Equalf(t, 4, d.lenopened(), "should have opened 4 connections")
909+
assert.Equalf(t, 0, p.availableConnectionCount(), "should have 0 idle connections in pool")
910+
assert.Equalf(t, 1, p.totalConnectionCount(), "should have 1 total connection in pool")
911+
912+
p.close(context.Background())
913+
})
843914
})
844915
t.Run("maintain", func(t *testing.T) {
845916
t.Parallel()

0 commit comments

Comments
 (0)