Skip to content

Commit ad4f187

Browse files
committed
GODRIVER-2219 Make maxConnecting configurable via ClientOptions or URI options. (#828)
1 parent f0843e9 commit ad4f187

File tree

8 files changed

+99
-11
lines changed

8 files changed

+99
-11
lines changed

mongo/client.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,13 @@ func (c *Client) configure(opts *options.ClientOptions) error {
546546
topology.WithMinConnections(func(uint64) uint64 { return *opts.MinPoolSize }),
547547
)
548548
}
549+
// MaxConnecting
550+
if opts.MaxConnecting != nil {
551+
serverOpts = append(
552+
serverOpts,
553+
topology.WithMaxConnecting(func(uint64) uint64 { return *opts.MaxConnecting }),
554+
)
555+
}
549556
// PoolMonitor
550557
if opts.PoolMonitor != nil {
551558
serverOpts = append(

mongo/options/clientoptions.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ type ClientOptions struct {
109109
MaxConnIdleTime *time.Duration
110110
MaxPoolSize *uint64
111111
MinPoolSize *uint64
112+
MaxConnecting *uint64
112113
PoolMonitor *event.PoolMonitor
113114
Monitor *event.CommandMonitor
114115
ServerMonitor *event.ServerMonitor
@@ -312,6 +313,10 @@ func (c *ClientOptions) ApplyURI(uri string) *ClientOptions {
312313
c.MinPoolSize = &cs.MinPoolSize
313314
}
314315

316+
if cs.MaxConnectingSet {
317+
c.MaxConnecting = &cs.MaxConnecting
318+
}
319+
315320
if cs.ReadConcernLevel != "" {
316321
c.ReadConcern = readconcern.New(readconcern.Level(cs.ReadConcernLevel))
317322
}
@@ -583,6 +588,14 @@ func (c *ClientOptions) SetMinPoolSize(u uint64) *ClientOptions {
583588
return c
584589
}
585590

591+
// SetMaxConnecting specifies the maximum number of connections a connection pool may establish simultaneously. This can
592+
// also be set through the "maxConnecting" URI option (e.g. "maxConnecting=2"). If this is 0, the default is used. The
593+
// default is 2. Values greater than 100 are not recommended.
594+
func (c *ClientOptions) SetMaxConnecting(u uint64) *ClientOptions {
595+
c.MaxConnecting = &u
596+
return c
597+
}
598+
586599
// SetPoolMonitor specifies a PoolMonitor to receive connection pool events. See the event.PoolMonitor documentation
587600
// for more information about the structure of the monitor and events that can be received.
588601
func (c *ClientOptions) SetPoolMonitor(m *event.PoolMonitor) *ClientOptions {
@@ -859,6 +872,9 @@ func MergeClientOptions(opts ...*ClientOptions) *ClientOptions {
859872
if opt.MinPoolSize != nil {
860873
c.MinPoolSize = opt.MinPoolSize
861874
}
875+
if opt.MaxConnecting != nil {
876+
c.MaxConnecting = opt.MaxConnecting
877+
}
862878
if opt.PoolMonitor != nil {
863879
c.PoolMonitor = opt.PoolMonitor
864880
}

mongo/options/clientoptions_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ func TestClientOptions(t *testing.T) {
6969
{"MaxConnIdleTime", (*ClientOptions).SetMaxConnIdleTime, 5 * time.Second, "MaxConnIdleTime", true},
7070
{"MaxPoolSize", (*ClientOptions).SetMaxPoolSize, uint64(250), "MaxPoolSize", true},
7171
{"MinPoolSize", (*ClientOptions).SetMinPoolSize, uint64(10), "MinPoolSize", true},
72+
{"MaxConnecting", (*ClientOptions).SetMaxConnecting, uint64(10), "MaxConnecting", true},
7273
{"PoolMonitor", (*ClientOptions).SetPoolMonitor, &event.PoolMonitor{}, "PoolMonitor", false},
7374
{"Monitor", (*ClientOptions).SetMonitor, &event.CommandMonitor{}, "Monitor", false},
7475
{"ReadConcern", (*ClientOptions).SetReadConcern, readconcern.Majority(), "ReadConcern", false},
@@ -338,6 +339,16 @@ func TestClientOptions(t *testing.T) {
338339
"mongodb://localhost/?maxPoolSize=256",
339340
baseClient().SetMaxPoolSize(256),
340341
},
342+
{
343+
"MinPoolSize",
344+
"mongodb://localhost/?minPoolSize=256",
345+
baseClient().SetMinPoolSize(256),
346+
},
347+
{
348+
"MaxConnecting",
349+
"mongodb://localhost/?maxConnecting=10",
350+
baseClient().SetMaxConnecting(10),
351+
},
341352
{
342353
"ReadConcern",
343354
"mongodb://localhost/?readConcernLevel=linearizable",

x/mongo/driver/connstring/connstring.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ type ConnString struct {
8585
MaxPoolSizeSet bool
8686
MinPoolSize uint64
8787
MinPoolSizeSet bool
88+
MaxConnecting uint64
89+
MaxConnectingSet bool
8890
Password string
8991
PasswordSet bool
9092
ReadConcernLevel string
@@ -731,6 +733,13 @@ func (p *parser) addOption(pair string) error {
731733
}
732734
p.MinPoolSize = uint64(n)
733735
p.MinPoolSizeSet = true
736+
case "maxconnecting":
737+
n, err := strconv.Atoi(value)
738+
if err != nil || n < 0 {
739+
return fmt.Errorf("invalid value for %s: %s", key, value)
740+
}
741+
p.MaxConnecting = uint64(n)
742+
p.MaxConnectingSet = true
734743
case "readconcernlevel":
735744
p.ReadConcernLevel = value
736745
case "readpreference":

x/mongo/driver/connstring/connstring_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,33 @@ func TestMinPoolSize(t *testing.T) {
319319
}
320320
}
321321

322+
func TestMaxConnecting(t *testing.T) {
323+
tests := []struct {
324+
s string
325+
expected uint64
326+
err bool
327+
}{
328+
{s: "maxConnecting=10", expected: 10},
329+
{s: "maxConnecting=100", expected: 100},
330+
{s: "maxConnecting=-2", err: true},
331+
{s: "maxConnecting=gsdge", err: true},
332+
}
333+
334+
for _, test := range tests {
335+
s := fmt.Sprintf("mongodb://localhost/?%s", test.s)
336+
t.Run(s, func(t *testing.T) {
337+
cs, err := connstring.ParseAndValidate(s)
338+
if test.err {
339+
require.Error(t, err)
340+
} else {
341+
require.NoError(t, err)
342+
require.True(t, cs.MaxConnectingSet)
343+
require.Equal(t, test.expected, cs.MaxConnecting)
344+
}
345+
})
346+
}
347+
}
348+
322349
func TestReadPreference(t *testing.T) {
323350
tests := []struct {
324351
s string

x/mongo/driver/topology/pool.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,12 @@ func (pe PoolError) Error() string { return string(pe) }
3838

3939
// poolConfig contains all aspects of the pool that can be configured
4040
type poolConfig struct {
41-
Address address.Address
42-
MinPoolSize uint64
43-
MaxPoolSize uint64
44-
MaxIdleTime time.Duration
45-
PoolMonitor *event.PoolMonitor
41+
Address address.Address
42+
MinPoolSize uint64
43+
MaxPoolSize uint64
44+
MaxConnecting uint64
45+
MaxIdleTime time.Duration
46+
PoolMonitor *event.PoolMonitor
4647
}
4748

4849
type pool struct {
@@ -100,11 +101,16 @@ func newPool(config poolConfig, connOpts ...ConnectionOption) *pool {
100101
connOpts = append(connOpts, WithIdleTimeout(func(_ time.Duration) time.Duration { return config.MaxIdleTime }))
101102
}
102103

104+
var maxConnecting uint64 = 2
105+
if config.MaxConnecting > 0 {
106+
maxConnecting = config.MaxConnecting
107+
}
108+
103109
pool := &pool{
104110
address: config.Address,
105111
minSize: config.MinPoolSize,
106112
maxSize: config.MaxPoolSize,
107-
maxConnecting: 2,
113+
maxConnecting: maxConnecting,
108114
monitor: config.PoolMonitor,
109115
connOpts: connOpts,
110116
generation: newPoolGenerationMap(),

x/mongo/driver/topology/server.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,12 @@ func NewServer(addr address.Address, topologyID primitive.ObjectID, opts ...Serv
178178
s.rttMonitor = newRTTMonitor(rttCfg)
179179

180180
pc := poolConfig{
181-
Address: addr,
182-
MinPoolSize: cfg.minConns,
183-
MaxPoolSize: cfg.maxConns,
184-
MaxIdleTime: cfg.connectionPoolMaxIdleTime,
185-
PoolMonitor: cfg.poolMonitor,
181+
Address: addr,
182+
MinPoolSize: cfg.minConns,
183+
MaxPoolSize: cfg.maxConns,
184+
MaxConnecting: cfg.maxConnecting,
185+
MaxIdleTime: cfg.connectionPoolMaxIdleTime,
186+
PoolMonitor: cfg.poolMonitor,
186187
}
187188

188189
connectionOpts := copyConnectionOpts(cfg.connectionOpts)

x/mongo/driver/topology/server_options.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type serverConfig struct {
2727
heartbeatTimeout time.Duration
2828
maxConns uint64
2929
minConns uint64
30+
maxConnecting uint64
3031
poolMonitor *event.PoolMonitor
3132
serverMonitor *event.ServerMonitor
3233
connectionPoolMaxIdleTime time.Duration
@@ -124,6 +125,16 @@ func WithMinConnections(fn func(uint64) uint64) ServerOption {
124125
}
125126
}
126127

128+
// WithMaxConnecting configures the maximum number of connections a connection
129+
// pool may establish simultaneously. If maxConnecting is 0, the default value
130+
// of 2 is used.
131+
func WithMaxConnecting(fn func(uint64) uint64) ServerOption {
132+
return func(cfg *serverConfig) error {
133+
cfg.maxConnecting = fn(cfg.maxConnecting)
134+
return nil
135+
}
136+
}
137+
127138
// WithConnectionPoolMaxIdleTime configures the maximum time that a connection can remain idle in the connection pool
128139
// before being removed. If connectionPoolMaxIdleTime is 0, then no idle time is set and connections will not be removed
129140
// because of their age

0 commit comments

Comments
 (0)