diff --git a/session.go b/session.go index edd43f717..61a9cb22d 100644 --- a/session.go +++ b/session.go @@ -342,6 +342,7 @@ func ParseURL(url string) (*DialInfo, error) { var readPreferenceTagSets []bson.D minPoolSize := 0 maxIdleTimeMS := 0 + safe := Safe{} for _, opt := range uinfo.options { switch opt.key { case "authSource": @@ -352,6 +353,23 @@ func ParseURL(url string) (*DialInfo, error) { service = opt.value case "replicaSet": setName = opt.value + case "w": + safe.WMode = opt.value + case "j": + journal, err := strconv.ParseBool(opt.value) + if err != nil { + return nil, errors.New("bad value for j: " + opt.value) + } + safe.J = journal + case "wtimeoutMS": + timeout, err := strconv.Atoi(opt.value) + if err != nil { + return nil, errors.New("bad value for wtimeoutMS: " + opt.value) + } + if timeout < 0 { + return nil, errors.New("bad value (negative) for wtimeoutMS: " + opt.value) + } + safe.WTimeout = timeout case "maxPoolSize": poolLimit, err = strconv.Atoi(opt.value) if err != nil { @@ -394,7 +412,7 @@ func ParseURL(url string) (*DialInfo, error) { return nil, errors.New("bad value for minPoolSize: " + opt.value) } if minPoolSize < 0 { - return nil, errors.New("bad value (negtive) for minPoolSize: " + opt.value) + return nil, errors.New("bad value (negative) for minPoolSize: " + opt.value) } case "maxIdleTimeMS": maxIdleTimeMS, err = strconv.Atoi(opt.value) @@ -402,7 +420,7 @@ func ParseURL(url string) (*DialInfo, error) { return nil, errors.New("bad value for maxIdleTimeMS: " + opt.value) } if maxIdleTimeMS < 0 { - return nil, errors.New("bad value (negtive) for maxIdleTimeMS: " + opt.value) + return nil, errors.New("bad value (negative) for maxIdleTimeMS: " + opt.value) } case "connect": if opt.value == "direct" { @@ -437,6 +455,7 @@ func ParseURL(url string) (*DialInfo, error) { Mode: readPreferenceMode, TagSets: readPreferenceTagSets, }, + Safe: safe, ReplicaSetName: setName, MinPoolSize: minPoolSize, MaxIdleTimeMS: maxIdleTimeMS, @@ -529,6 +548,9 @@ type DialInfo struct { // Session.SetMode and Session.SelectServers. ReadPreference *ReadPreference + // Safe mostly defines write options, though there is RMode. See Session.SetSafe + Safe Safe + // FailFast will cause connection and query attempts to fail faster when // the server is unavailable, instead of retrying until the configured // timeout period. Note that an unavailable server may silently drop @@ -715,6 +737,8 @@ func DialWithInfo(dialInfo *DialInfo) (*Session, error) { return nil, err } + session.SetSafe(&info.Safe) + if info.ReadPreference != nil { session.SelectServers(info.ReadPreference.TagSets...) session.SetMode(info.ReadPreference.Mode, true) diff --git a/session_test.go b/session_test.go index 14cb9b1a6..23396434d 100644 --- a/session_test.go +++ b/session_test.go @@ -168,6 +168,43 @@ func (s *S) TestURLInvalidReadPreference(c *C) { } } +func (s *S) TestURLSafe(c *C) { + type test struct { + url string + safe mgo.Safe + } + + tests := []test{ + {"localhost:40001?w=majority", mgo.Safe{WMode: "majority"}}, + {"localhost:40001?j=true", mgo.Safe{J: true}}, + {"localhost:40001?j=false", mgo.Safe{J: false}}, + {"localhost:40001?wtimeoutMS=1", mgo.Safe{WTimeout: 1}}, + {"localhost:40001?wtimeoutMS=1000", mgo.Safe{WTimeout: 1000}}, + {"localhost:40001?w=1&j=true&wtimeoutMS=1000", mgo.Safe{WMode: "1", J: true, WTimeout: 1000}}, + } + + for _, test := range tests { + info, err := mgo.ParseURL(test.url) + c.Assert(err, IsNil) + c.Assert(info.Safe, NotNil) + c.Assert(info.Safe, Equals, test.safe) + } +} + +func (s *S) TestURLInvalidSafe(c *C) { + urls := []string{ + "localhost:40001?wtimeoutMS=abc", + "localhost:40001?wtimeoutMS=", + "localhost:40001?wtimeoutMS=-1", + "localhost:40001?j=12", + "localhost:40001?j=foo", + } + for _, url := range urls { + _, err := mgo.ParseURL(url) + c.Assert(err, NotNil) + } +} + func (s *S) TestMinPoolSize(c *C) { tests := []struct { url string