From c34812f1154d1e1ba88e9649cad44514cce95171 Mon Sep 17 00:00:00 2001 From: Preston Vasquez Date: Tue, 30 Apr 2024 09:41:12 -0600 Subject: [PATCH 1/4] HELP-58644 Add RequireNew option --- mongo/client.go | 3 +++ mongo/options/sessionoptions.go | 13 +++++++++++++ x/mongo/driver/session/client_session.go | 11 ++++++++++- x/mongo/driver/session/options.go | 4 ++++ 4 files changed, 30 insertions(+), 1 deletion(-) 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..30753e56b3 100644 --- a/mongo/options/sessionoptions.go +++ b/mongo/options/sessionoptions.go @@ -48,6 +48,10 @@ 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 a call to [Client.StartSession] creates a new + // server session rather than checking one out from the pool. + RequireNew *bool } // Session creates a new SessionOptions instance. @@ -96,6 +100,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 +135,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..10eb0fc1f3 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,12 @@ 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() + } 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 From b963c52648efc9f5bc0b1f268c4c030dd77e406b Mon Sep 17 00:00:00 2001 From: Preston Vasquez Date: Tue, 30 Apr 2024 09:45:20 -0600 Subject: [PATCH 2/4] HELP-58644 Update field comment --- mongo/options/sessionoptions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mongo/options/sessionoptions.go b/mongo/options/sessionoptions.go index 30753e56b3..b256d0b46c 100644 --- a/mongo/options/sessionoptions.go +++ b/mongo/options/sessionoptions.go @@ -49,7 +49,7 @@ type SessionOptions struct { // snapshot sessions and will error. The default value is false. Snapshot *bool - // RequireNew ensures that a call to [Client.StartSession] creates a new + // RequireNew ensures that starting a session with a client creates a new // server session rather than checking one out from the pool. RequireNew *bool } From 582ee8d26ea132ecfb030e05dc484b12f8bf9440 Mon Sep 17 00:00:00 2001 From: Preston Vasquez Date: Tue, 30 Apr 2024 09:50:56 -0600 Subject: [PATCH 3/4] HELP-58644 Clarify RequireNew usage --- mongo/options/sessionoptions.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mongo/options/sessionoptions.go b/mongo/options/sessionoptions.go index b256d0b46c..09d481df1b 100644 --- a/mongo/options/sessionoptions.go +++ b/mongo/options/sessionoptions.go @@ -50,7 +50,8 @@ type SessionOptions struct { Snapshot *bool // RequireNew ensures that starting a session with a client creates a new - // server session rather than checking one out from the pool. + // 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 } From d2da455889483dcdb67487b68d1927129930ccba Mon Sep 17 00:00:00 2001 From: Preston Vasquez Date: Wed, 1 May 2024 20:19:33 -0600 Subject: [PATCH 4/4] HELP-58644 Mark single-checkout servers as dirty --- x/mongo/driver/session/client_session.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/x/mongo/driver/session/client_session.go b/x/mongo/driver/session/client_session.go index 10eb0fc1f3..0fdcd54c41 100644 --- a/x/mongo/driver/session/client_session.go +++ b/x/mongo/driver/session/client_session.go @@ -236,6 +236,11 @@ func (c *Client) SetServer() error { var err error 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() }