Skip to content

GODRIVER-1659 fail fast during server selection if incompatible WireVersion #461

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
1 change: 1 addition & 0 deletions x/mongo/driver/description/topology.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type Topology struct {
Servers []Server
Kind TopologyKind
SessionTimeoutMinutes uint32
CompatibilityErr error
}

// Server returns the server for the given address. Returns false if the server
Expand Down
6 changes: 4 additions & 2 deletions x/mongo/driver/topology/fsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ func (f *fsm) apply(s description.Server) (description.Topology, description.Ser
supportedWireVersions.Min,
minSupportedMongoDBVersion,
)
return description.Topology{}, s, f.compatibilityErr
f.Topology.CompatibilityErr = f.compatibilityErr
return f.Topology, s, nil
}

if server.WireVersion.Min > supportedWireVersions.Max {
Expand All @@ -110,7 +111,8 @@ func (f *fsm) apply(s description.Server) (description.Topology, description.Ser
server.WireVersion.Min,
supportedWireVersions.Max,
)
return description.Topology{}, s, f.compatibilityErr
f.Topology.CompatibilityErr = f.compatibilityErr
return f.Topology, s, nil
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions x/mongo/driver/topology/topology.go
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,10 @@ func (t *Topology) selectServerFromDescription(desc description.Topology,
// Unlike selectServerFromSubscription, this code path does not check ctx.Done or selectionState.timeoutChan because
// selecting a server from a description is not a blocking operation.

if desc.CompatibilityErr != nil {
return nil, desc.CompatibilityErr
}

var allowed []description.Server
for _, s := range desc.Servers {
if s.Kind != description.Unknown {
Expand Down
49 changes: 49 additions & 0 deletions x/mongo/driver/topology/topology_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package topology
import (
"context"
"errors"
"fmt"
"sync/atomic"
"testing"
"time"
Expand Down Expand Up @@ -84,6 +85,54 @@ func TestServerSelection(t *testing.T) {
t.Errorf("Incorrect sever selected. got %s; want %s", srvs[0].Addr, desc.Servers[0].Addr)
}
})
t.Run("Compatibility Error Min Version Too High", func(t *testing.T) {
topo, err := New()
noerr(t, err)
desc := description.Topology{
Kind: description.Single,
Servers: []description.Server{
{Addr: address.Address("one:27017"), Kind: description.Standalone, WireVersion: &description.VersionRange{Max: 11, Min: 11}},
{Addr: address.Address("two:27017"), Kind: description.Standalone, WireVersion: &description.VersionRange{Max: 9, Min: 2}},
{Addr: address.Address("three:27017"), Kind: description.Standalone, WireVersion: &description.VersionRange{Max: 9, Min: 2}},
},
}
want := fmt.Errorf(
"server at %s requires wire version %d, but this version of the Go driver only supports up to %d",
desc.Servers[0].Addr.String(),
desc.Servers[0].WireVersion.Min,
supportedWireVersions.Max,
)
desc.CompatibilityErr = want
atomic.StoreInt32(&topo.connectionstate, connected)
topo.desc.Store(desc)
_, err = topo.SelectServer(context.Background(), selectFirst)
assert.Equal(t, err, want, "expected %v, got %v", want, err)
})
t.Run("Compatibility Error Max Version Too Low", func(t *testing.T) {
topo, err := New()
noerr(t, err)
desc := description.Topology{
Kind: description.Single,
Servers: []description.Server{
{Addr: address.Address("one:27017"), Kind: description.Standalone, WireVersion: &description.VersionRange{Max: 1, Min: 1}},
{Addr: address.Address("two:27017"), Kind: description.Standalone, WireVersion: &description.VersionRange{Max: 9, Min: 2}},
{Addr: address.Address("three:27017"), Kind: description.Standalone, WireVersion: &description.VersionRange{Max: 9, Min: 2}},
},
}
want := fmt.Errorf(
"server at %s reports wire version %d, but this version of the Go driver requires "+
"at least %d (MongoDB %s)",
desc.Servers[0].Addr.String(),
desc.Servers[0].WireVersion.Max,
supportedWireVersions.Min,
minSupportedMongoDBVersion,
)
desc.CompatibilityErr = want
atomic.StoreInt32(&topo.connectionstate, connected)
topo.desc.Store(desc)
_, err = topo.SelectServer(context.Background(), selectFirst)
assert.Equal(t, err, want, "expected %v, got %v", want, err)
})
t.Run("Updated", func(t *testing.T) {
topo, err := New()
noerr(t, err)
Expand Down