-
Type: Bug
-
Resolution: Gone away
-
Priority: Major - P3
-
None
-
Affects Version/s: None
-
Component/s: Server Selection
I'm creating a client that has a secondary preferred read preference with max staleness set as well. When selecting a server, sometimes the version will not be available in the candidate version (due to possibly not having looked up information yet on the server?) which erroneously causes any operation to fail since the driver thinks the feature is not supported.
I think this a race condition. Say there's just one server in the topology. The condition happens where the topology is partially discovered and during selection we check the feature on the partial server description which will have a missing version. Normally this is okay but it immediately causes an error instead of recognizing that this server is a partial, no candidate has been selected as suitable, and calling RequestImmediateCheck instead.
EDIT: Upon further inspection, I think this is caused by buildInfo being lost on subsequent heartbeats (see: https://github.com/mongodb/mongo-go-driver/blob/master/core/topology/server.go#L381)
This untested patch may work:
diff --git a/core/topology/server.go b/core/topology/server.go index 0bbc027..3f05a98 100644 --- a/core/topology/server.go +++ b/core/topology/server.go @@ -339,6 +339,7 @@ func (s *Server) heartbeat(conn connection.Connection) (description.Server, conn var desc description.Server var set bool var err error + currDesc := s.desc.Load().(description.Server) ctx := context.Background() for i := 1; i <= maxRetry; i++ { if conn != nil && conn.Expired() { @@ -357,7 +358,10 @@ func (s *Server) heartbeat(conn connection.Connection) (description.Server, conn opts = append(opts, connection.WithHandshaker(func(h connection.Handshaker) connection.Handshaker { return nil })) - conn, _, err = connection.New(ctx, s.address, opts...) + var connDesc *description.Server + if conn, connDesc, err = connection.New(ctx, s.address, opts...); connDesc != nil { + currDesc = *connDesc + } if err != nil { saved = err if conn != nil { @@ -378,7 +382,11 @@ func (s *Server) heartbeat(conn connection.Connection) (description.Server, conn } delay := time.Since(now) - desc = description.NewServer(s.address, isMaster, result.BuildInfo{}).SetAverageRTT(s.updateAverageRTT(delay)) + desc = description.NewServer(s.address, isMaster, result.BuildInfo{ + GitVersion: currDesc.GitVersion, + Version: currDesc.Version.Desc, + VersionArray: currDesc.Version.Parts, + }).SetAverageRTT(s.updateAverageRTT(delay)) desc.HeartbeatInterval = s.cfg.heartbeatInterval set = true
- is caused by
-
GODRIVER-441 Connection Handshake should not call buildInfo
- Closed