Skip to content

Commit c2b6752

Browse files
committed
Merge branch 'GODRVIER-396' of https://github.com/igorKryvenko/mongo-go-driver into master
Change-Id: I2b71ac4e4f8e0b5d6b51e57c14b97a79da6c4038
2 parents 2f097c7 + 2674041 commit c2b6752

File tree

6 files changed

+114
-1
lines changed

6 files changed

+114
-1
lines changed

core/connstring/connstring.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ type ConnString struct {
6161
ReadConcernLevel string
6262
ReadPreference string
6363
ReadPreferenceTagSets []map[string]string
64+
MaxStaleness time.Duration
65+
MaxStalenessSet bool
6466
ReplicaSet string
6567
ServerSelectionTimeout time.Duration
6668
ServerSelectionTimeoutSet bool
@@ -444,6 +446,13 @@ func (p *parser) addOption(pair string) error {
444446
tags[parts[0]] = parts[1]
445447
}
446448
p.ReadPreferenceTagSets = append(p.ReadPreferenceTagSets, tags)
449+
case "maxstaleness":
450+
n, err := strconv.Atoi(value)
451+
if err != nil || n < 0 {
452+
return fmt.Errorf("invalid value for %s: %s", key, value)
453+
}
454+
p.MaxStaleness = time.Duration(n) * time.Second
455+
p.MaxStalenessSet = true
447456
case "replicaset":
448457
p.ReplicaSet = value
449458
case "serverselectiontimeoutms":

core/connstring/connstring_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,31 @@ func TestReadPreferenceTags(t *testing.T) {
359359
}
360360
}
361361

362+
func TestMaxStaleness(t *testing.T) {
363+
tests := []struct {
364+
s string
365+
expected time.Duration
366+
err bool
367+
}{
368+
{s: "maxStaleness=10", expected: time.Duration(10) * time.Second},
369+
{s: "maxStaleness=100", expected: time.Duration(100) * time.Second},
370+
{s: "maxStaleness=-2", err: true},
371+
{s: "maxStaleness=gsdge", err: true},
372+
}
373+
for _, test := range tests {
374+
s := fmt.Sprintf("mongodb://localhost/?%s", test.s)
375+
t.Run(s, func(t *testing.T) {
376+
cs, err := connstring.Parse(s)
377+
if test.err {
378+
require.Error(t, err)
379+
} else {
380+
require.NoError(t, err)
381+
require.Equal(t, test.expected, cs.MaxStaleness)
382+
}
383+
})
384+
}
385+
}
386+
362387
func TestReplicaSet(t *testing.T) {
363388
tests := []struct {
364389
s string

mongo/client.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/mongodb/mongo-go-driver/core/options"
1818
"github.com/mongodb/mongo-go-driver/core/readconcern"
1919
"github.com/mongodb/mongo-go-driver/core/readpref"
20+
"github.com/mongodb/mongo-go-driver/core/tag"
2021
"github.com/mongodb/mongo-go-driver/core/topology"
2122
"github.com/mongodb/mongo-go-driver/core/writeconcern"
2223
)
@@ -97,7 +98,6 @@ func newClient(cs connstring.ConnString, opts *ClientOptions) (*Client, error) {
9798
client := &Client{
9899
connString: cs,
99100
localThreshold: defaultLocalThreshold,
100-
readPreference: readpref.Primary(),
101101
}
102102

103103
if opts != nil {
@@ -122,6 +122,10 @@ func newClient(cs connstring.ConnString, opts *ClientOptions) (*Client, error) {
122122
client.topology = topo
123123
client.readConcern = readConcernFromConnString(&client.connString)
124124
client.writeConcern = writeConcernFromConnString(&client.connString)
125+
client.readPreference, err = readPreferenceFromConnString(&client.connString)
126+
if err != nil {
127+
return nil, err
128+
}
125129

126130
return client, nil
127131
}
@@ -173,6 +177,31 @@ func writeConcernFromConnString(cs *connstring.ConnString) *writeconcern.WriteCo
173177
return wc
174178
}
175179

180+
func readPreferenceFromConnString(cs *connstring.ConnString) (*readpref.ReadPref, error) {
181+
var rp *readpref.ReadPref
182+
var err error
183+
options := make([]readpref.Option, 0, 1)
184+
185+
tagSets := tag.NewTagSetsFromMaps(cs.ReadPreferenceTagSets)
186+
if len(tagSets) > 0 {
187+
options = append(options, readpref.WithTagSets(tagSets...))
188+
}
189+
190+
if cs.MaxStaleness != 0 {
191+
options = append(options, readpref.WithMaxStaleness(cs.MaxStaleness))
192+
}
193+
if len(cs.ReadPreference) > 0 {
194+
if rp == nil {
195+
mode, _ := readpref.ModeFromString(cs.ReadPreference)
196+
rp, err = readpref.New(mode, options...)
197+
if err != nil {
198+
return nil, err
199+
}
200+
}
201+
}
202+
return rp, nil
203+
}
204+
176205
// Database returns a handle for a given database.
177206
func (c *Client) Database(name string) *Database {
178207
return newDatabase(c, name)

mongo/client_internal_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,11 @@ import (
1616

1717
"github.com/mongodb/mongo-go-driver/bson"
1818
"github.com/mongodb/mongo-go-driver/core/readpref"
19+
"github.com/mongodb/mongo-go-driver/core/tag"
1920
"github.com/mongodb/mongo-go-driver/internal/testutil"
2021
"github.com/stretchr/testify/require"
22+
23+
"time"
2124
)
2225

2326
func createTestClient(t *testing.T) *Client {
@@ -296,3 +299,37 @@ func TestClient_ListDatabaseNames_filter(t *testing.T) {
296299
require.Len(t, dbs, 1)
297300
require.Equal(t, dbName, dbs[0])
298301
}
302+
303+
func TestClient_ReadPreference(t *testing.T) {
304+
t.Parallel()
305+
306+
if testing.Short() {
307+
t.Skip()
308+
}
309+
var tags = []tag.Set{
310+
{
311+
tag.Tag{
312+
Name: "one",
313+
Value: "1",
314+
},
315+
},
316+
{
317+
tag.Tag{
318+
Name: "two",
319+
Value: "2",
320+
},
321+
},
322+
}
323+
baseConnString := testutil.ConnString(t)
324+
cs := testutil.AddOptionsToURI(baseConnString.String(), "readpreference=secondary&readPreferenceTags=one:1&readPreferenceTags=two:2&maxStaleness=5")
325+
326+
c, err := NewClient(cs)
327+
require.NoError(t, err)
328+
require.NotNil(t, c)
329+
require.Equal(t, readpref.SecondaryMode, c.readPreference.Mode())
330+
require.Equal(t, tags, c.readPreference.TagSets())
331+
d, flag := c.readPreference.MaxStaleness()
332+
require.True(t, flag)
333+
require.Equal(t, time.Duration(5)*time.Second, d)
334+
335+
}

mongo/client_options.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,18 @@ func (co *ClientOptions) ReadPreferenceTagSets(m []map[string]string) *ClientOpt
247247
return &ClientOptions{next: co, opt: fn}
248248
}
249249

250+
//MaxStaleness sets the "maxStaleness" field of the read pref to set on the client.
251+
func (co *ClientOptions) MaxStaleness(d time.Duration) *ClientOptions {
252+
var fn option = func(c *Client) error {
253+
if !c.connString.MaxStalenessSet {
254+
c.connString.MaxStaleness = d
255+
c.connString.MaxStalenessSet = true
256+
}
257+
return nil
258+
}
259+
return &ClientOptions{next: co, opt: fn}
260+
}
261+
250262
// ReplicaSet specifies the name of the replica set of the cluster.
251263
func (co *ClientOptions) ReplicaSet(s string) *ClientOptions {
252264
var fn option = func(c *Client) error {

mongo/client_options_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ func TestClientOptions_chainAll(t *testing.T) {
8080
ReadPreference("secondary").
8181
ReadPreferenceTagSets([]map[string]string{
8282
{"nyc": "1"}}).
83+
MaxStaleness(2 * time.Second).
8384
ReplicaSet("foo").
8485
ServerSelectionTimeout(time.Second).
8586
Single(false).

0 commit comments

Comments
 (0)