Skip to content

Commit c6a8120

Browse files
rfblue2Roland Fong
authored andcommitted
Add mongo/clientopt
GODRIVER-272 GODRIVER-450 Change-Id: I90ca993fc7605b71a4b32283694af68a68a9279d
1 parent 6c086d6 commit c6a8120

File tree

5 files changed

+794
-59
lines changed

5 files changed

+794
-59
lines changed

mongo/client.go

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/mongodb/mongo-go-driver/core/tag"
2121
"github.com/mongodb/mongo-go-driver/core/topology"
2222
"github.com/mongodb/mongo-go-driver/core/writeconcern"
23+
"github.com/mongodb/mongo-go-driver/mongo/clientopt"
2324
)
2425

2526
const defaultLocalThreshold = 15 * time.Millisecond
@@ -36,8 +37,8 @@ type Client struct {
3637
}
3738

3839
// Connect creates a new Client and then initializes it using the Connect method.
39-
func Connect(ctx context.Context, uri string, opts *ClientOptions) (*Client, error) {
40-
c, err := NewClientWithOptions(uri, opts)
40+
func Connect(ctx context.Context, uri string, opts ...clientopt.Option) (*Client, error) {
41+
c, err := NewClientWithOptions(uri, opts...)
4142
if err != nil {
4243
return nil, err
4344
}
@@ -61,13 +62,13 @@ func NewClient(uri string) (*Client, error) {
6162
// NewClientWithOptions creates a new client to connect to to a cluster specified by the connection
6263
// string and the options manually passed in. If the same option is configured in both the
6364
// connection string and the manual options, the manual option will be ignored.
64-
func NewClientWithOptions(uri string, opts *ClientOptions) (*Client, error) {
65+
func NewClientWithOptions(uri string, opts ...clientopt.Option) (*Client, error) {
6566
cs, err := connstring.Parse(uri)
6667
if err != nil {
6768
return nil, err
6869
}
6970

70-
return newClient(cs, opts)
71+
return newClient(cs, opts...)
7172
}
7273

7374
// NewClientFromConnString creates a new client to connect to a cluster, with configuration
@@ -94,20 +95,16 @@ func (c *Client) Disconnect(ctx context.Context) error {
9495
return c.topology.Disconnect(ctx)
9596
}
9697

97-
func newClient(cs connstring.ConnString, opts *ClientOptions) (*Client, error) {
98-
client := &Client{
99-
connString: cs,
100-
localThreshold: defaultLocalThreshold,
98+
func newClient(cs connstring.ConnString, opts ...clientopt.Option) (*Client, error) {
99+
clientOpt, err := clientopt.BundleClient(opts...).Unbundle(cs)
100+
if err != nil {
101+
return nil, err
101102
}
102103

103-
if opts != nil {
104-
for opts.opt != nil {
105-
err := opts.opt(client)
106-
if err != nil {
107-
return nil, err
108-
}
109-
opts = opts.next
110-
}
104+
client := &Client{
105+
topologyOptions: clientOpt.TopologyOptions,
106+
connString: clientOpt.ConnString,
107+
localThreshold: defaultLocalThreshold,
111108
}
112109

113110
topts := append(
@@ -120,19 +117,23 @@ func newClient(cs connstring.ConnString, opts *ClientOptions) (*Client, error) {
120117
}
121118
client.topology = topo
122119

123-
client.readConcern = readConcernFromConnString(&client.connString)
124-
client.writeConcern = writeConcernFromConnString(&client.connString)
125-
126-
rp, err := readPreferenceFromConnString(&client.connString)
127-
if err != nil {
128-
return nil, err
120+
if client.readConcern == nil {
121+
client.readConcern = readConcernFromConnString(&client.connString)
129122
}
130-
if rp != nil {
131-
client.readPreference = rp
132-
} else {
133-
client.readPreference = readpref.Primary()
123+
if client.writeConcern == nil {
124+
client.writeConcern = writeConcernFromConnString(&client.connString)
125+
}
126+
if client.readPreference == nil {
127+
rp, err := readPreferenceFromConnString(&client.connString)
128+
if err != nil {
129+
return nil, err
130+
}
131+
if rp != nil {
132+
client.readPreference = rp
133+
} else {
134+
client.readPreference = readpref.Primary()
135+
}
134136
}
135-
136137
return client, nil
137138
}
138139

mongo/client_internal_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121
"github.com/stretchr/testify/require"
2222

2323
"time"
24+
25+
"github.com/mongodb/mongo-go-driver/mongo/clientopt"
2426
)
2527

2628
func createTestClient(t *testing.T) *Client {
@@ -49,6 +51,22 @@ func TestClient_Database(t *testing.T) {
4951
require.Exactly(t, c, db.Client())
5052
}
5153

54+
func TestClientOptions(t *testing.T) {
55+
t.Parallel()
56+
57+
c, err := NewClientWithOptions("mongodb://localhost",
58+
clientopt.MaxConnIdleTime(200),
59+
clientopt.ReplicaSet("test"),
60+
clientopt.LocalThreshold(10),
61+
clientopt.MaxConnIdleTime(100),
62+
clientopt.LocalThreshold(20))
63+
require.NoError(t, err)
64+
65+
require.Equal(t, time.Duration(20), c.connString.LocalThreshold)
66+
require.Equal(t, time.Duration(100), c.connString.MaxConnIdleTime)
67+
require.Equal(t, "test", c.connString.ReplicaSet)
68+
}
69+
5270
func TestClient_TLSConnection(t *testing.T) {
5371
t.Parallel()
5472

mongo/client_options_test.go

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ import (
99
"time"
1010

1111
"github.com/mongodb/mongo-go-driver/core/connstring"
12+
"github.com/mongodb/mongo-go-driver/core/readconcern"
13+
"github.com/mongodb/mongo-go-driver/core/readpref"
14+
"github.com/mongodb/mongo-go-driver/core/tag"
15+
"github.com/mongodb/mongo-go-driver/core/writeconcern"
1216
"github.com/mongodb/mongo-go-driver/internal/testutil"
17+
"github.com/mongodb/mongo-go-driver/mongo/clientopt"
1318
"github.com/stretchr/testify/require"
1419
)
1520

@@ -21,7 +26,7 @@ func TestClientOptions_simple(t *testing.T) {
2126
}
2227

2328
cs := testutil.ConnString(t)
24-
client, err := NewClientWithOptions(cs.String(), ClientOpt.AppName("foo"))
29+
client, err := NewClientWithOptions(cs.String(), clientopt.AppName("foo"))
2530
require.NoError(t, err)
2631

2732
require.Equal(t, "foo", client.connString.AppName)
@@ -37,7 +42,7 @@ func TestClientOptions_deferToConnString(t *testing.T) {
3742
cs := testutil.ConnString(t)
3843
uri := testutil.AddOptionsToURI(cs.String(), "appname=bar")
3944

40-
client, err := NewClientWithOptions(uri, ClientOpt.AppName("foo"))
45+
client, err := NewClientWithOptions(uri, clientopt.AppName("foo"))
4146
require.NoError(t, err)
4247

4348
require.Equal(t, "bar", client.connString.AppName)
@@ -47,7 +52,7 @@ func TestClientOptions_doesNotAlterConnectionString(t *testing.T) {
4752
t.Parallel()
4853

4954
cs := connstring.ConnString{}
50-
client, err := newClient(cs, ClientOpt.AppName("foobar"))
55+
client, err := newClient(cs, clientopt.AppName("foobar"))
5156
require.NoError(t, err)
5257
if cs.AppName != "" {
5358
t.Errorf("Creating a new Client should not alter the original connection string, but it did. got %s; want <empty>", cs.AppName)
@@ -59,53 +64,60 @@ func TestClientOptions_doesNotAlterConnectionString(t *testing.T) {
5964

6065
func TestClientOptions_chainAll(t *testing.T) {
6166
t.Parallel()
62-
63-
opts := ClientOpt.
67+
readPrefMode, err := readpref.ModeFromString("secondary")
68+
require.NoError(t, err)
69+
rp, err := readpref.New(
70+
readPrefMode,
71+
readpref.WithTagSets(tag.NewTagSetsFromMaps([]map[string]string{{"nyc": "1"}})...),
72+
readpref.WithMaxStaleness(2*time.Second),
73+
)
74+
require.NoError(t, err)
75+
opts := clientopt.BundleClient().
6476
AppName("foo").
65-
AuthMechanism("MONGODB-X509").
66-
AuthMechanismProperties(map[string]string{"foo": "bar"}).
67-
AuthSource("$external").
77+
Auth(clientopt.Credential{
78+
AuthMechanism: "MONGODB-X509",
79+
AuthMechanismProperties: map[string]string{"foo": "bar"},
80+
AuthSource: "$external",
81+
Password: "supersecurepassword",
82+
Username: "admin",
83+
}).
6884
ConnectTimeout(500 * time.Millisecond).
6985
HeartbeatInterval(15 * time.Second).
7086
Hosts([]string{
7187
"mongodb://localhost:27018",
7288
"mongodb://localhost:27019"}).
73-
Journal(true).
7489
LocalThreshold(time.Second).
7590
MaxConnIdleTime(30 * time.Second).
7691
MaxConnsPerHost(150).
7792
MaxIdleConnsPerHost(20).
78-
Password("supersecurepassword").
79-
ReadConcernLevel("majority").
80-
ReadPreference("secondary").
81-
ReadPreferenceTagSets([]map[string]string{
82-
{"nyc": "1"}}).
83-
MaxStaleness(2 * time.Second).
93+
ReadConcern(readconcern.New(readconcern.Level("majority"))).
94+
ReadPreference(rp).
8495
ReplicaSet("foo").
8596
ServerSelectionTimeout(time.Second).
8697
Single(false).
8798
SocketTimeout(2 * time.Second).
88-
SSL(true).
89-
SSLClientCertificateKeyFile("client.pem").
90-
SSLClientCertificateKeyPassword(func() string { return "password" }).
91-
SSLInsecure(false).
92-
SSLCaFile("ca.pem").
93-
WString("majority").
94-
WNumber(3).
95-
Username("admin").
96-
WTimeout(2 * time.Second)
97-
98-
client := new(Client)
99-
for opts.opt != nil {
100-
err := opts.opt(client)
101-
require.NoError(t, err)
102-
opts = opts.next
103-
}
99+
SSL(&clientopt.SSLOpt{
100+
Enabled: true,
101+
ClientCertificateKeyFile: "client.pem",
102+
ClientCertificateKeyPassword: func() string { return "password" },
103+
Insecure: false,
104+
CaFile: "ca.pem",
105+
}).
106+
WriteConcern(writeconcern.New(
107+
writeconcern.J(true),
108+
writeconcern.WTagSet("majority"),
109+
writeconcern.W(3),
110+
writeconcern.WTimeout(2*time.Second),
111+
))
112+
113+
client, err := opts.Unbundle(connstring.ConnString{})
114+
require.NoError(t, err)
115+
require.NotNil(t, client)
104116
}
105117

106118
func TestClientOptions_CustomDialer(t *testing.T) {
107119
td := &testDialer{d: &net.Dialer{}}
108-
opts := ClientOpt.Dialer(td)
120+
opts := clientopt.Dialer(td)
109121
client, err := newClient(testutil.ConnString(t), opts)
110122
require.NoError(t, err)
111123
err = client.Connect(context.Background())

0 commit comments

Comments
 (0)