diff --git a/mongo/client.go b/mongo/client.go index 588d741fa2..c717594167 100644 --- a/mongo/client.go +++ b/mongo/client.go @@ -408,6 +408,9 @@ func (c *Client) StartSession(opts ...*options.SessionOptions) (Session, error) if sopts.Snapshot != nil { coreOpts.Snapshot = sopts.Snapshot } + if sopts.RequireNew != nil { + coreOpts.RequireNew = sopts.RequireNew + } sess, err := session.NewClientSession(c.sessionPool, c.id, coreOpts) if err != nil { diff --git a/mongo/options/sessionoptions.go b/mongo/options/sessionoptions.go index e1eab098be..09d481df1b 100644 --- a/mongo/options/sessionoptions.go +++ b/mongo/options/sessionoptions.go @@ -48,6 +48,11 @@ type SessionOptions struct { // be set to true if CausalConsistency is set to true. Transactions and write operations are not allowed on // snapshot sessions and will error. The default value is false. Snapshot *bool + + // RequireNew ensures that starting a session with a client creates a new + // server session rather than checking one out from the pool. Since this + // avoids pooling, closing the server session is up to the caller. + RequireNew *bool } // Session creates a new SessionOptions instance. @@ -96,6 +101,12 @@ func (s *SessionOptions) SetSnapshot(b bool) *SessionOptions { return s } +// SetRequireNew sets the value for the RequireNew field. +func (s *SessionOptions) SetRequireNew(b bool) *SessionOptions { + s.RequireNew = &b + return s +} + // MergeSessionOptions combines the given SessionOptions instances into a single SessionOptions in a last-one-wins // fashion. // @@ -125,6 +136,9 @@ func MergeSessionOptions(opts ...*SessionOptions) *SessionOptions { if opt.Snapshot != nil { s.Snapshot = opt.Snapshot } + if opt.RequireNew != nil { + s.RequireNew = opt.RequireNew + } } if s.CausalConsistency == nil && (s.Snapshot == nil || !*s.Snapshot) { s.CausalConsistency = &DefaultCausalConsistency diff --git a/x/mongo/driver/session/client_session.go b/x/mongo/driver/session/client_session.go index 8dac0932de..0fdcd54c41 100644 --- a/x/mongo/driver/session/client_session.go +++ b/x/mongo/driver/session/client_session.go @@ -133,6 +133,7 @@ type Client struct { RecoveryToken bson.Raw PinnedConnection LoadBalancedTransactionConnection SnapshotTime *primitive.Timestamp + RequireNew bool } func getClusterTime(clusterTime bson.Raw) (uint32, uint32) { @@ -207,6 +208,9 @@ func NewClientSession(pool *Pool, clientID uuid.UUID, opts ...*ClientOptions) (* if mergedOpts.Snapshot != nil { c.Snapshot = *mergedOpts.Snapshot } + if mergedOpts.RequireNew != nil { + c.RequireNew = *mergedOpts.RequireNew + } // For explicit sessions, the default for causalConsistency is true, unless Snapshot is // enabled, then it's false. Set the default and then allow any explicit causalConsistency @@ -230,7 +234,17 @@ func NewClientSession(pool *Pool, clientID uuid.UUID, opts ...*ClientOptions) (* // SetServer will check out a session from the client session pool. func (c *Client) SetServer() error { var err error - c.Server, err = c.pool.GetSession() + if c.RequireNew { + c.Server, err = newServerSession() + + // Mark the server as dirty so that it won't be returned to the pool. + if c.Server != nil { + c.Server.MarkDirty() + } + } else { + c.Server, err = c.pool.GetSession() + } + return err } diff --git a/x/mongo/driver/session/options.go b/x/mongo/driver/session/options.go index ee7c301d64..c40b96b557 100644 --- a/x/mongo/driver/session/options.go +++ b/x/mongo/driver/session/options.go @@ -22,6 +22,7 @@ type ClientOptions struct { DefaultReadPreference *readpref.ReadPref DefaultMaxCommitTime *time.Duration Snapshot *bool + RequireNew *bool } // TransactionOptions represents all possible options for starting a transaction in a session. @@ -56,6 +57,9 @@ func mergeClientOptions(opts ...*ClientOptions) *ClientOptions { if opt.Snapshot != nil { c.Snapshot = opt.Snapshot } + if opt.RequireNew != nil { + c.RequireNew = opt.RequireNew + } } return c