Skip to content

Commit a50f838

Browse files
author
iwysiu
authored
GODRIVER-1572 add TopologyVersion (#403)
1 parent a7e2372 commit a50f838

File tree

5 files changed

+117
-250
lines changed

5 files changed

+117
-250
lines changed

x/mongo/driver/description/server.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ type Server struct {
5050
SetVersion uint32
5151
SpeculativeAuthenticate bsoncore.Document
5252
Tags tag.Set
53+
TopologyVersion *TopologyVersion
5354
Kind ServerKind
5455
WireVersion *VersionRange
5556

@@ -239,13 +240,32 @@ func NewServer(addr address.Address, response bsoncore.Document) Server {
239240
return desc
240241
}
241242
desc.SetVersion = uint32(i64)
243+
case "speculativeAuthenticate":
244+
desc.SpeculativeAuthenticate, ok = element.Value().DocumentOK()
245+
if !ok {
246+
desc.LastError = fmt.Errorf("expected 'speculativeAuthenticate' to be a document but it's a BSON %s",
247+
element.Value().Type)
248+
return desc
249+
}
242250
case "tags":
243251
m, err := decodeStringMap(element, "tags")
244252
if err != nil {
245253
desc.LastError = err
246254
return desc
247255
}
248256
desc.Tags = tag.NewTagSetFromMap(m)
257+
case "topologyVersion":
258+
doc, ok := element.Value().DocumentOK()
259+
if !ok {
260+
desc.LastError = fmt.Errorf("expected 'topologyVersion' to be a document but it's a BSON %s", element.Value().Type)
261+
return desc
262+
}
263+
264+
desc.TopologyVersion, err = NewTopologyVersion(doc)
265+
if err != nil {
266+
desc.LastError = err
267+
return desc
268+
}
249269
}
250270
}
251271

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (C) MongoDB, Inc. 2017-present.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License"); you may
4+
// not use this file except in compliance with the License. You may obtain
5+
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
package description
8+
9+
import (
10+
"fmt"
11+
12+
"go.mongodb.org/mongo-driver/bson/primitive"
13+
"go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
14+
)
15+
16+
// TopologyVersion represents a software version.
17+
type TopologyVersion struct {
18+
ProcessID primitive.ObjectID
19+
Counter int64
20+
}
21+
22+
// NewTopologyVersion creates a TopologyVersion based on doc
23+
func NewTopologyVersion(doc bsoncore.Document) (*TopologyVersion, error) {
24+
elements, err := doc.Elements()
25+
if err != nil {
26+
return nil, err
27+
}
28+
var tv TopologyVersion
29+
var ok bool
30+
for _, element := range elements {
31+
switch element.Key() {
32+
case "processId":
33+
tv.ProcessID, ok = element.Value().ObjectIDOK()
34+
if !ok {
35+
return nil, fmt.Errorf("expected 'processId' to be a objectID but it's a BSON %s", element.Value().Type)
36+
}
37+
case "counter":
38+
tv.Counter, ok = element.Value().Int64OK()
39+
if !ok {
40+
return nil, fmt.Errorf("expected 'counter' to be an int64 but it's a BSON %s", element.Value().Type)
41+
}
42+
}
43+
}
44+
return &tv, nil
45+
}
46+
47+
// MoreRecentThan returns if this TopologyVersion is more recent than the one passed in.
48+
// This should be called on the original TopologyVersion with the new one passed in.
49+
func (tv *TopologyVersion) MoreRecentThan(other *TopologyVersion) bool {
50+
if tv == nil || other == nil {
51+
return false
52+
}
53+
if tv.ProcessID != other.ProcessID {
54+
return false
55+
}
56+
57+
return tv.Counter > other.Counter
58+
}

x/mongo/driver/errors.go

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,12 @@ func (wce WriteCommandError) Retryable(wireVersion *description.VersionRange) bo
116116
// WriteConcernError is a write concern failure that occurred as a result of a
117117
// write operation.
118118
type WriteConcernError struct {
119-
Name string
120-
Code int64
121-
Message string
122-
Details bsoncore.Document
123-
Labels []string
119+
Name string
120+
Code int64
121+
Message string
122+
Details bsoncore.Document
123+
Labels []string
124+
TopologyVersion *description.TopologyVersion
124125
}
125126

126127
func (wce WriteConcernError) Error() string {
@@ -200,11 +201,12 @@ func (we WriteErrors) Error() string {
200201

201202
// Error is a command execution error from the database.
202203
type Error struct {
203-
Code int32
204-
Message string
205-
Labels []string
206-
Name string
207-
Wrapped error
204+
Code int32
205+
Message string
206+
Labels []string
207+
Name string
208+
Wrapped error
209+
TopologyVersion *description.TopologyVersion
208210
}
209211

210212
// UnsupportedStorageEngine returns whether e came as a result of an unsupported storage engine
@@ -324,6 +326,7 @@ func extractError(rdr bsoncore.Document) error {
324326
var code int32
325327
var labels []string
326328
var ok bool
329+
var tv *description.TopologyVersion
327330
var wcError WriteCommandError
328331
elems, err := rdr.Elements()
329332
if err != nil {
@@ -428,6 +431,15 @@ func extractError(rdr bsoncore.Document) error {
428431
}
429432
}
430433
}
434+
case "topologyVersion":
435+
doc, ok := elem.Value().DocumentOK()
436+
if !ok {
437+
break
438+
}
439+
version, err := description.NewTopologyVersion(doc)
440+
if err == nil {
441+
tv = version
442+
}
431443
}
432444
}
433445

@@ -437,15 +449,19 @@ func extractError(rdr bsoncore.Document) error {
437449
}
438450

439451
return Error{
440-
Code: code,
441-
Message: errmsg,
442-
Name: codeName,
443-
Labels: labels,
452+
Code: code,
453+
Message: errmsg,
454+
Name: codeName,
455+
Labels: labels,
456+
TopologyVersion: tv,
444457
}
445458
}
446459

447460
if len(wcError.WriteErrors) > 0 || wcError.WriteConcernError != nil {
448461
wcError.Labels = labels
462+
if wcError.WriteConcernError != nil {
463+
wcError.WriteConcernError.TopologyVersion = tv
464+
}
449465
return wcError
450466
}
451467

0 commit comments

Comments
 (0)