Skip to content

Commit a9223ce

Browse files
authored
GODRIVER-1659 fail fast during server selection if incompatible WireVersion (#461)
1 parent 46d5d76 commit a9223ce

File tree

4 files changed

+58
-2
lines changed

4 files changed

+58
-2
lines changed

x/mongo/driver/description/topology.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type Topology struct {
1717
Servers []Server
1818
Kind TopologyKind
1919
SessionTimeoutMinutes uint32
20+
CompatibilityErr error
2021
}
2122

2223
// Server returns the server for the given address. Returns false if the server

x/mongo/driver/topology/fsm.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ func (f *fsm) apply(s description.Server) (description.Topology, description.Ser
9999
supportedWireVersions.Min,
100100
minSupportedMongoDBVersion,
101101
)
102-
return description.Topology{}, s, f.compatibilityErr
102+
f.Topology.CompatibilityErr = f.compatibilityErr
103+
return f.Topology, s, nil
103104
}
104105

105106
if server.WireVersion.Min > supportedWireVersions.Max {
@@ -110,7 +111,8 @@ func (f *fsm) apply(s description.Server) (description.Topology, description.Ser
110111
server.WireVersion.Min,
111112
supportedWireVersions.Max,
112113
)
113-
return description.Topology{}, s, f.compatibilityErr
114+
f.Topology.CompatibilityErr = f.compatibilityErr
115+
return f.Topology, s, nil
114116
}
115117
}
116118
}

x/mongo/driver/topology/topology.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,10 @@ func (t *Topology) selectServerFromDescription(desc description.Topology,
455455
// Unlike selectServerFromSubscription, this code path does not check ctx.Done or selectionState.timeoutChan because
456456
// selecting a server from a description is not a blocking operation.
457457

458+
if desc.CompatibilityErr != nil {
459+
return nil, desc.CompatibilityErr
460+
}
461+
458462
var allowed []description.Server
459463
for _, s := range desc.Servers {
460464
if s.Kind != description.Unknown {

x/mongo/driver/topology/topology_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ package topology
99
import (
1010
"context"
1111
"errors"
12+
"fmt"
1213
"sync/atomic"
1314
"testing"
1415
"time"
@@ -84,6 +85,54 @@ func TestServerSelection(t *testing.T) {
8485
t.Errorf("Incorrect sever selected. got %s; want %s", srvs[0].Addr, desc.Servers[0].Addr)
8586
}
8687
})
88+
t.Run("Compatibility Error Min Version Too High", func(t *testing.T) {
89+
topo, err := New()
90+
noerr(t, err)
91+
desc := description.Topology{
92+
Kind: description.Single,
93+
Servers: []description.Server{
94+
{Addr: address.Address("one:27017"), Kind: description.Standalone, WireVersion: &description.VersionRange{Max: 11, Min: 11}},
95+
{Addr: address.Address("two:27017"), Kind: description.Standalone, WireVersion: &description.VersionRange{Max: 9, Min: 2}},
96+
{Addr: address.Address("three:27017"), Kind: description.Standalone, WireVersion: &description.VersionRange{Max: 9, Min: 2}},
97+
},
98+
}
99+
want := fmt.Errorf(
100+
"server at %s requires wire version %d, but this version of the Go driver only supports up to %d",
101+
desc.Servers[0].Addr.String(),
102+
desc.Servers[0].WireVersion.Min,
103+
supportedWireVersions.Max,
104+
)
105+
desc.CompatibilityErr = want
106+
atomic.StoreInt32(&topo.connectionstate, connected)
107+
topo.desc.Store(desc)
108+
_, err = topo.SelectServer(context.Background(), selectFirst)
109+
assert.Equal(t, err, want, "expected %v, got %v", want, err)
110+
})
111+
t.Run("Compatibility Error Max Version Too Low", func(t *testing.T) {
112+
topo, err := New()
113+
noerr(t, err)
114+
desc := description.Topology{
115+
Kind: description.Single,
116+
Servers: []description.Server{
117+
{Addr: address.Address("one:27017"), Kind: description.Standalone, WireVersion: &description.VersionRange{Max: 1, Min: 1}},
118+
{Addr: address.Address("two:27017"), Kind: description.Standalone, WireVersion: &description.VersionRange{Max: 9, Min: 2}},
119+
{Addr: address.Address("three:27017"), Kind: description.Standalone, WireVersion: &description.VersionRange{Max: 9, Min: 2}},
120+
},
121+
}
122+
want := fmt.Errorf(
123+
"server at %s reports wire version %d, but this version of the Go driver requires "+
124+
"at least %d (MongoDB %s)",
125+
desc.Servers[0].Addr.String(),
126+
desc.Servers[0].WireVersion.Max,
127+
supportedWireVersions.Min,
128+
minSupportedMongoDBVersion,
129+
)
130+
desc.CompatibilityErr = want
131+
atomic.StoreInt32(&topo.connectionstate, connected)
132+
topo.desc.Store(desc)
133+
_, err = topo.SelectServer(context.Background(), selectFirst)
134+
assert.Equal(t, err, want, "expected %v, got %v", want, err)
135+
})
87136
t.Run("Updated", func(t *testing.T) {
88137
topo, err := New()
89138
noerr(t, err)

0 commit comments

Comments
 (0)