Skip to content

Commit 0c36a32

Browse files
authored
NODE-2474: update equal server description (#2260)
Ensure the server description is updated even when equal to the previous one, to keep client-tracked attributes fresh. NODE-2474
1 parent 6b3b64d commit 0c36a32

File tree

4 files changed

+267
-21
lines changed

4 files changed

+267
-21
lines changed

lib/core/sdam/topology.js

+25-21
Original file line numberDiff line numberDiff line change
@@ -519,10 +519,10 @@ class Topology extends EventEmitter {
519519
}
520520

521521
// If we already know all the information contained in this updated description, then
522-
// we don't need to update anything or emit SDAM events
523-
if (previousServerDescription && previousServerDescription.equals(serverDescription)) {
524-
return;
525-
}
522+
// we don't need to emit SDAM events, but still need to update the description, in order
523+
// to keep client-tracked attributes like last update time and round trip time up to date
524+
const equalDescriptions =
525+
previousServerDescription && previousServerDescription.equals(serverDescription);
526526

527527
// first update the TopologyDescription
528528
this.s.description = this.s.description.update(serverDescription);
@@ -532,15 +532,17 @@ class Topology extends EventEmitter {
532532
}
533533

534534
// emit monitoring events for this change
535-
this.emit(
536-
'serverDescriptionChanged',
537-
new events.ServerDescriptionChangedEvent(
538-
this.s.id,
539-
serverDescription.address,
540-
previousServerDescription,
541-
this.s.description.servers.get(serverDescription.address)
542-
)
543-
);
535+
if (!equalDescriptions) {
536+
this.emit(
537+
'serverDescriptionChanged',
538+
new events.ServerDescriptionChangedEvent(
539+
this.s.id,
540+
serverDescription.address,
541+
previousServerDescription,
542+
this.s.description.servers.get(serverDescription.address)
543+
)
544+
);
545+
}
544546

545547
// update server list from updated descriptions
546548
updateServers(this, serverDescription);
@@ -550,14 +552,16 @@ class Topology extends EventEmitter {
550552
processWaitQueue(this);
551553
}
552554

553-
this.emit(
554-
'topologyDescriptionChanged',
555-
new events.TopologyDescriptionChangedEvent(
556-
this.s.id,
557-
previousTopologyDescription,
558-
this.s.description
559-
)
560-
);
555+
if (!equalDescriptions) {
556+
this.emit(
557+
'topologyDescriptionChanged',
558+
new events.TopologyDescriptionChangedEvent(
559+
this.s.id,
560+
previousTopologyDescription,
561+
this.s.description
562+
)
563+
);
564+
}
561565
}
562566

563567
auth(credentials, callback) {

test/functional/core/replset_state.test.js

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ describe('ReplicaSet state', function() {
1212

1313
fs.readdirSync(path)
1414
.filter(x => x.indexOf('.json') !== -1)
15+
.filter(x => !x.includes('repeated'))
1516
.forEach(x => {
1617
var testData = require(f('%s/%s', path, x));
1718

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
{
2+
"description": "Repeated ismaster response must be processed",
3+
"uri": "mongodb://a,b/?replicaSet=rs",
4+
"phases": [
5+
{
6+
"responses": [
7+
[
8+
"a:27017",
9+
{
10+
"ok": 1,
11+
"ismaster": false,
12+
"secondary": true,
13+
"hidden": true,
14+
"hosts": [
15+
"a:27017",
16+
"c:27017"
17+
],
18+
"setName": "rs",
19+
"minWireVersion": 0,
20+
"maxWireVersion": 6
21+
}
22+
]
23+
],
24+
"outcome": {
25+
"servers": {
26+
"a:27017": {
27+
"type": "RSOther",
28+
"setName": "rs"
29+
},
30+
"b:27017": {
31+
"type": "Unknown"
32+
},
33+
"c:27017": {
34+
"type": "Unknown"
35+
}
36+
},
37+
"topologyType": "ReplicaSetNoPrimary",
38+
"logicalSessionTimeoutMinutes": null,
39+
"setName": "rs"
40+
}
41+
},
42+
{
43+
"responses": [
44+
[
45+
"c:27017",
46+
{
47+
"ok": 1,
48+
"ismaster": true,
49+
"minWireVersion": 0,
50+
"maxWireVersion": 6
51+
}
52+
]
53+
],
54+
"outcome": {
55+
"servers": {
56+
"a:27017": {
57+
"type": "RSOther",
58+
"setName": "rs"
59+
},
60+
"b:27017": {
61+
"type": "Unknown"
62+
}
63+
},
64+
"topologyType": "ReplicaSetNoPrimary",
65+
"logicalSessionTimeoutMinutes": null,
66+
"setName": "rs"
67+
}
68+
},
69+
{
70+
"responses": [
71+
[
72+
"a:27017",
73+
{
74+
"ok": 1,
75+
"ismaster": false,
76+
"secondary": true,
77+
"hidden": true,
78+
"hosts": [
79+
"a:27017",
80+
"c:27017"
81+
],
82+
"setName": "rs",
83+
"minWireVersion": 0,
84+
"maxWireVersion": 6
85+
}
86+
]
87+
],
88+
"outcome": {
89+
"servers": {
90+
"a:27017": {
91+
"type": "RSOther",
92+
"setName": "rs"
93+
},
94+
"b:27017": {
95+
"type": "Unknown"
96+
},
97+
"c:27017": {
98+
"type": "Unknown"
99+
}
100+
},
101+
"topologyType": "ReplicaSetNoPrimary",
102+
"logicalSessionTimeoutMinutes": null,
103+
"setName": "rs"
104+
}
105+
},
106+
{
107+
"responses": [
108+
[
109+
"c:27017",
110+
{
111+
"ok": 1,
112+
"ismaster": true,
113+
"hosts": [
114+
"a:27017",
115+
"c:27017"
116+
],
117+
"setName": "rs",
118+
"minWireVersion": 0,
119+
"maxWireVersion": 6
120+
}
121+
]
122+
],
123+
"outcome": {
124+
"servers": {
125+
"a:27017": {
126+
"type": "RSOther",
127+
"setName": "rs"
128+
},
129+
"c:27017": {
130+
"type": "RSPrimary",
131+
"setName": "rs"
132+
}
133+
},
134+
"topologyType": "ReplicaSetWithPrimary",
135+
"logicalSessionTimeoutMinutes": null,
136+
"setName": "rs"
137+
}
138+
}
139+
]
140+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
description: Repeated ismaster response must be processed
2+
3+
uri: "mongodb://a,b/?replicaSet=rs"
4+
5+
phases:
6+
# Phase 1 - a says it's not primary and suggests c may be the primary
7+
- responses:
8+
-
9+
- "a:27017"
10+
- ok: 1
11+
ismaster: false
12+
secondary: true
13+
hidden: true
14+
hosts: ["a:27017", "c:27017"]
15+
setName: "rs"
16+
minWireVersion: 0
17+
maxWireVersion: 6
18+
outcome:
19+
servers:
20+
"a:27017":
21+
type: "RSOther"
22+
setName: "rs"
23+
24+
"b:27017":
25+
type: Unknown
26+
27+
"c:27017":
28+
type: Unknown
29+
topologyType: "ReplicaSetNoPrimary"
30+
logicalSessionTimeoutMinutes: ~
31+
setName: "rs"
32+
33+
# Phase 2 - c says it's a standalone, is removed
34+
- responses:
35+
-
36+
- "c:27017"
37+
- ok: 1
38+
ismaster: true
39+
minWireVersion: 0
40+
maxWireVersion: 6
41+
outcome:
42+
servers:
43+
"a:27017":
44+
type: "RSOther"
45+
setName: "rs"
46+
47+
"b:27017":
48+
type: Unknown
49+
topologyType: "ReplicaSetNoPrimary"
50+
logicalSessionTimeoutMinutes: ~
51+
setName: "rs"
52+
53+
# Phase 3 - response from a is repeated, and must be processed; c added again
54+
- responses:
55+
-
56+
- "a:27017"
57+
- ok: 1
58+
ismaster: false
59+
secondary: true
60+
hidden: true
61+
hosts: ["a:27017", "c:27017"]
62+
setName: "rs"
63+
minWireVersion: 0
64+
maxWireVersion: 6
65+
outcome:
66+
servers:
67+
"a:27017":
68+
type: "RSOther"
69+
setName: "rs"
70+
71+
"b:27017":
72+
type: Unknown
73+
74+
"c:27017":
75+
type: Unknown
76+
topologyType: "ReplicaSetNoPrimary"
77+
logicalSessionTimeoutMinutes: ~
78+
setName: "rs"
79+
80+
# Phase 4 - c is now a primary
81+
- responses:
82+
-
83+
- "c:27017"
84+
- ok: 1
85+
ismaster: true
86+
hosts: ["a:27017", "c:27017"]
87+
setName: "rs"
88+
minWireVersion: 0
89+
maxWireVersion: 6
90+
outcome:
91+
servers:
92+
"a:27017":
93+
type: "RSOther"
94+
setName: "rs"
95+
96+
"c:27017":
97+
type: RSPrimary
98+
setName: rs
99+
topologyType: "ReplicaSetWithPrimary"
100+
logicalSessionTimeoutMinutes: ~
101+
setName: "rs"

0 commit comments

Comments
 (0)