Skip to content
This repository was archived by the owner on Oct 18, 2021. It is now read-only.

Commit 2509772

Browse files
authored
Merge pull request #157 from saghm/set-version
Implement using `setVersion` to detect stale primaries
2 parents 8f6917f + c61a325 commit 2509772

File tree

4 files changed

+36
-17
lines changed

4 files changed

+36
-17
lines changed

src/topology/mod.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ pub struct TopologyDescription {
6060
// If true, all servers in the topology fall within the compatible
6161
// mongodb version for this driver.
6262
compatible: bool,
63+
// The largest set version seen from a primary in the topology.
64+
max_set_version: Option<i64>,
6365
compat_error: String,
6466
}
6567

@@ -98,6 +100,7 @@ impl TopologyDescription {
98100
max_election_id: None,
99101
compatible: true,
100102
compat_error: String::new(),
103+
max_set_version: None,
101104
}
102105
}
103106

@@ -560,23 +563,29 @@ impl TopologyDescription {
560563
return;
561564
}
562565

563-
if description.election_id.is_some() {
564-
if self.max_election_id.is_some() &&
565-
self.max_election_id.as_ref().unwrap() > description.election_id.as_ref().unwrap() {
566-
// Stale primary
567-
if let Some(server) = self.servers.get(&host) {
568-
{
569-
let mut server_description = server.description.write().unwrap();
570-
server_description.server_type = ServerType::Unknown;
571-
server_description.set_name = String::new();
572-
server_description.election_id = None;
566+
if description.set_version.is_some() && description.election_id.is_some() {
567+
if self.max_set_version.is_some() && self.max_election_id.is_some() &&
568+
(self.max_set_version.unwrap() > description.set_version.unwrap() ||
569+
(self.max_set_version.unwrap() == description.set_version.unwrap() &&
570+
self.max_election_id.as_ref().unwrap() > description.election_id.as_ref().unwrap())) {
571+
// Stale primary
572+
if let Some(server) = self.servers.get(&host) {
573+
{
574+
let mut server_description = server.description.write().unwrap();
575+
server_description.server_type = ServerType::Unknown;
576+
server_description.set_name = String::new();
577+
server_description.election_id = None;
578+
}
579+
}
580+
self.check_if_has_primary();
581+
return;
582+
} else {
583+
self.max_election_id = description.election_id.clone();
573584
}
574-
}
575-
self.check_if_has_primary();
576-
return;
577-
} else {
578-
self.max_election_id = description.election_id.clone();
579-
}
585+
}
586+
587+
if description.set_version.is_some() && (self.max_set_version.is_none() || description.set_version.unwrap() > self.max_set_version.unwrap()) {
588+
self.max_set_version = description.set_version;
580589
}
581590

582591
// Invalidate any old primaries

src/topology/monitor.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub struct IsMasterResult {
5353
pub election_id: Option<oid::ObjectId>,
5454
pub primary: Option<Host>,
5555
pub hidden: bool,
56+
pub set_version: Option<i64>,
5657
}
5758

5859
/// Monitors and updates server and topology information.
@@ -112,6 +113,7 @@ impl IsMasterResult {
112113
election_id: None,
113114
primary: None,
114115
hidden: false,
116+
set_version: None,
115117
};
116118

117119
if let Some(&Bson::Boolean(b)) = doc.get("ismaster") {
@@ -183,6 +185,10 @@ impl IsMasterResult {
183185
result.hidden = *h;
184186
}
185187

188+
if let Some(&Bson::I64(v)) = doc.get("setVersion") {
189+
result.set_version = Some(v);
190+
}
191+
186192
if let Some(&Bson::Document(ref doc)) = doc.get("tags") {
187193
for (k, v) in doc.into_iter() {
188194
if let &Bson::String(ref tag) = v {

src/topology/server.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ pub struct ServerDescription {
7171
pub election_id: Option<oid::ObjectId>,
7272
/// The server's opinion of who the primary is.
7373
pub primary: Option<Host>,
74+
/// The current replica set version number.
75+
pub set_version: Option<i64>,
7476
}
7577

7678
/// Holds status and connection information about a single server.
@@ -119,6 +121,7 @@ impl ServerDescription {
119121
set_name: String::new(),
120122
election_id: None,
121123
primary: None,
124+
set_version: None,
122125
}
123126
}
124127

@@ -139,6 +142,7 @@ impl ServerDescription {
139142
self.set_name = ismaster.set_name;
140143
self.election_id = ismaster.election_id;
141144
self.primary = ismaster.primary;
145+
self.set_version = ismaster.set_version;
142146
self.round_trip_time = match self.round_trip_time {
143147
Some(old_rtt) => {
144148
// (rtt / div) + (old_rtt * (div-1)/div)

tests/json/data/specs

Submodule specs updated 191 files

0 commit comments

Comments
 (0)