Skip to content
This repository was archived by the owner on Feb 4, 2022. It is now read-only.

Commit de0105c

Browse files
committed
fix(sessions): ensure that we ignore session details from arbiters
Arbiters in a ReplSet should not be taken into consideration if they report a `logicalSessionTimeoutMinutes`. NODE-1188
1 parent 65dcca4 commit de0105c

File tree

2 files changed

+54
-34
lines changed

2 files changed

+54
-34
lines changed

lib/topologies/replset_state.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ ReplSetState.prototype.remove = function(server, options) {
200200
}
201201
};
202202

203+
const isArbiter = ismaster => ismaster.arbiterOnly && ismaster.setName;
204+
203205
ReplSetState.prototype.update = function(server) {
204206
var self = this;
205207
// Get the current ismaster
@@ -266,7 +268,7 @@ ReplSetState.prototype.update = function(server) {
266268
}
267269

268270
// Update logicalSessionTimeoutMinutes
269-
if (ismaster.logicalSessionTimeoutMinutes !== undefined) {
271+
if (ismaster.logicalSessionTimeoutMinutes !== undefined && !isArbiter(ismaster)) {
270272
if (
271273
self.logicalSessionTimeoutMinutes === undefined ||
272274
ismaster.logicalSessionTimeoutMinutes === null
@@ -597,8 +599,7 @@ ReplSetState.prototype.update = function(server) {
597599
// Arbiter handling
598600
//
599601
if (
600-
ismaster.arbiterOnly &&
601-
ismaster.setName &&
602+
isArbiter(ismaster) &&
602603
!inList(ismaster, server, this.arbiters) &&
603604
this.setName &&
604605
this.setName === ismaster.setName

test/tests/unit/replset/sessions_tests.js

+50-31
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ var expect = require('chai').expect,
88
const test = new ReplSetFixture();
99
describe('Sessions (ReplSet)', function() {
1010
afterEach(() => mock.cleanup());
11-
beforeEach(() => test.setup());
11+
beforeEach(() => test.setup({ ismaster: mock.DEFAULT_ISMASTER_36 }));
1212

1313
it('should track the highest `clusterTime` seen in a replica set', {
1414
metadata: { requires: { topology: 'single' } },
@@ -31,14 +31,10 @@ describe('Sessions (ReplSet)', function() {
3131
}
3232
);
3333

34-
let serverCount = 0;
35-
replset.on('joined', () => {
36-
serverCount++;
37-
if (serverCount === 3) {
38-
expect(replset.clusterTime).to.eql(futureClusterTime);
39-
replset.destroy();
40-
done();
41-
}
34+
replset.on('all', () => {
35+
expect(replset.clusterTime).to.eql(futureClusterTime);
36+
replset.destroy();
37+
done();
4238
});
4339

4440
replset.on('error', done);
@@ -67,19 +63,15 @@ describe('Sessions (ReplSet)', function() {
6763
}
6864
);
6965

70-
let serverCount = 0;
71-
replset.on('joined', () => {
72-
serverCount++;
73-
if (serverCount === 3) {
74-
expect(replset.clusterTime).to.eql(futureClusterTime);
75-
const servers = replset.s.replicaSetState.secondaries
76-
.concat(replset.s.replicaSetState.arbiters)
77-
.concat([replset.s.replicaSetState.primary]);
78-
servers.forEach(server => expect(server.clusterTime).to.eql(futureClusterTime));
66+
replset.on('all', () => {
67+
expect(replset.clusterTime).to.eql(futureClusterTime);
68+
const servers = replset.s.replicaSetState.secondaries
69+
.concat(replset.s.replicaSetState.arbiters)
70+
.concat([replset.s.replicaSetState.primary]);
71+
servers.forEach(server => expect(server.clusterTime).to.eql(futureClusterTime));
7972

80-
replset.destroy();
81-
done();
82-
}
73+
replset.destroy();
74+
done();
8375
});
8476

8577
replset.on('error', done);
@@ -90,6 +82,8 @@ describe('Sessions (ReplSet)', function() {
9082
it('should set `logicalSessionTimeoutMinutes` to `null` if any incoming server is `null`', {
9183
metadata: { requires: { topology: 'single' } },
9284
test: function(done) {
85+
test.firstSecondaryStates[0].logicalSessionTimeoutMinutes = null;
86+
9387
const replset = new ReplSet(
9488
[test.primaryServer.address(), test.firstSecondaryServer.address()],
9589
{
@@ -102,7 +96,7 @@ describe('Sessions (ReplSet)', function() {
10296
);
10397

10498
replset.on('error', done);
105-
replset.once('connect', () => {
99+
replset.once('all', () => {
106100
expect(replset.logicalSessionTimeoutMinutes).to.equal(null);
107101
replset.destroy();
108102
done();
@@ -132,20 +126,45 @@ describe('Sessions (ReplSet)', function() {
132126
}
133127
);
134128

135-
let joinCount = 0;
136-
replset.on('joined', () => {
137-
joinCount++;
138-
139-
if (joinCount === 3) {
140-
expect(replset.logicalSessionTimeoutMinutes).to.equal(1);
141-
replset.destroy();
142-
done();
143-
}
129+
replset.on('all', () => {
130+
expect(replset.logicalSessionTimeoutMinutes).to.equal(1);
131+
replset.destroy();
132+
done();
144133
});
145134

146135
replset.on('error', done);
147136
replset.connect();
148137
}
149138
}
150139
);
140+
141+
it('should exclude arbiters when tracking `logicalSessionTimeoutMinutes`', {
142+
metadata: { requires: { topology: 'single' } },
143+
test: function(done) {
144+
test.arbiterServer.setMessageHandler(req => {
145+
const doc = req.document;
146+
if (doc.ismaster) {
147+
req.reply(Object.assign({}, test.arbiterStates[0], { logicalSessionTimeoutMinutes: 2 }));
148+
}
149+
});
150+
151+
const replset = new ReplSet(test.servers.map(s => s.address()), {
152+
setName: 'rs',
153+
connectionTimeout: 3000,
154+
socketTimeout: 0,
155+
haInterval: 100,
156+
size: 1
157+
});
158+
159+
replset.on('joined', type => {
160+
if (type === 'arbiter') {
161+
expect(replset.logicalSessionTimeoutMinutes).to.equal(10);
162+
done();
163+
}
164+
});
165+
166+
replset.on('error', done);
167+
replset.connect();
168+
}
169+
});
151170
});

0 commit comments

Comments
 (0)