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

Commit ae820f6

Browse files
committed
fix(pool): ensure that lsid is sent in get requests to mongos
There is a strange case, when topology is mongos and readPreference is not primary, where we nest our find queries in a "$query" attribute. This was having the effect of not sending the lsid on find requests, which caused further errors when getMores attempted to send an lsid. Fixes NODE-1420
1 parent 468d1ff commit ae820f6

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

lib/connection/pool.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -1222,7 +1222,11 @@ Pool.prototype.write = function(commands, options, cb) {
12221222
// decorate the commands with session-specific details
12231223
commands.forEach(command => {
12241224
if (command instanceof Query) {
1225-
Object.assign(command.query, sessionOptions);
1225+
if (command.query.$query) {
1226+
Object.assign(command.query.$query, sessionOptions);
1227+
} else {
1228+
Object.assign(command.query, sessionOptions);
1229+
}
12261230
} else {
12271231
Object.assign(command, sessionOptions);
12281232
}

test/tests/unit/mongos/sessions_tests.js

+66
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ var Mongos = require('../../../../lib/topologies/mongos'),
44
mock = require('mongodb-mock-server'),
55
genClusterTime = require('../common').genClusterTime;
66

7+
const sessions = require('../../../../lib/sessions');
8+
const ServerSessionPool = sessions.ServerSessionPool;
9+
const ClientSession = sessions.ClientSession;
10+
const ReadPreference = require('../../../../lib/topologies/read_preference');
11+
712
const test = {};
813
describe('Sessions (Mongos)', function() {
914
afterEach(() => mock.cleanup());
@@ -161,4 +166,65 @@ describe('Sessions (Mongos)', function() {
161166
mongos.connect();
162167
}
163168
});
169+
170+
it(
171+
'should ensure that lsid is received within the query object of a find request when read preference is not primary',
172+
{
173+
metadata: { requires: { topology: 'single' } },
174+
test: function(done) {
175+
const clusterTime = genClusterTime(Date.now());
176+
test.server.setMessageHandler(request => {
177+
const doc = request.document;
178+
if (doc.ismaster) {
179+
request.reply(
180+
Object.assign({}, mock.DEFAULT_ISMASTER_36, {
181+
msg: 'isdbgrid',
182+
$clusterTime: clusterTime
183+
})
184+
);
185+
} else if (doc.$query) {
186+
try {
187+
expect(doc.$readPreference).to.deep.equal({ mode: 'primaryPreferred' });
188+
expect(doc)
189+
.to.haveOwnProperty('$query')
190+
.to.haveOwnProperty('lsid')
191+
.that.is.an('object');
192+
done();
193+
} catch (e) {
194+
done(e);
195+
}
196+
} else {
197+
done('YOU HAVE FAILED. WE WILL FIND ANOTHER WAY. RELEASING CONTROL');
198+
}
199+
});
200+
201+
const mongos = new Mongos([test.server.address()], {
202+
connectionTimeout: 30000,
203+
socketTimeout: 30000,
204+
haInterval: 500,
205+
size: 1
206+
});
207+
208+
mongos.on('error', done);
209+
mongos.once('connect', () => {
210+
const namespace = 'testdb.testcollection';
211+
const findCommand = {
212+
find: namespace
213+
};
214+
const pool = new ServerSessionPool(mongos);
215+
const session = new ClientSession(mongos, pool);
216+
const readPreference = new ReadPreference('primaryPreferred');
217+
218+
const cursor = mongos.cursor('testdb.testcollection', findCommand, {
219+
session,
220+
readPreference
221+
});
222+
223+
cursor.next(() => {});
224+
});
225+
226+
mongos.connect();
227+
}
228+
}
229+
);
164230
});

0 commit comments

Comments
 (0)