Skip to content

Commit a9097f7

Browse files
committed
feat(causal-consistency): support afterClusterTime in readConcern
NODE-1106
1 parent 052dc02 commit a9097f7

File tree

3 files changed

+72
-5
lines changed

3 files changed

+72
-5
lines changed

lib/collection.js

+16-4
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,9 @@ Collection.prototype.find = function() {
367367

368368
// Merge in options to command
369369
for (var name in newOptions) {
370-
if (newOptions[name] != null) findCommand[name] = newOptions[name];
370+
if (newOptions[name] != null && name !== 'session') {
371+
findCommand[name] = newOptions[name];
372+
}
371373
}
372374

373375
// Format the fields
@@ -2403,13 +2405,23 @@ function decorateWithCollation(command, self, options) {
24032405
}
24042406
}
24052407

2406-
function decorateWithReadConcern(command, self, options) { // eslint-disable-line
2407-
let readConcern = {};
2408+
function decorateWithReadConcern(command, self, options) {
2409+
let readConcern = Object.assign({}, command.readConcern || {});
24082410
if (self.s.readConcern) {
24092411
Object.assign(readConcern, self.s.readConcern);
24102412
}
24112413

2412-
Object.assign(command, readConcern);
2414+
if (
2415+
options.session &&
2416+
options.session.supports.causalConsistency &&
2417+
options.session.operationTime
2418+
) {
2419+
Object.assign(readConcern, { afterClusterTime: options.session.operationTime });
2420+
}
2421+
2422+
if (Object.keys(readConcern).length > 0) {
2423+
Object.assign(command, { readConcern: readConcern });
2424+
}
24132425
}
24142426

24152427
/**

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"official"
1414
],
1515
"dependencies": {
16-
"mongodb-core": "mongodb-js/mongodb-core#3.0.0"
16+
"mongodb-core": "mongodb-js/mongodb-core#causally-consistent-reads"
1717
},
1818
"devDependencies": {
1919
"betterbenchmarks": "^0.1.0",
+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
'use strict';
2+
const MongoClient = require('../../..').MongoClient,
3+
Timestamp = require('bson').Timestamp,
4+
expect = require('chai').expect,
5+
mock = require('../../mock');
6+
7+
const test = {};
8+
describe('Sessions', function() {
9+
describe('Collection', function() {
10+
afterEach(() => mock.cleanup());
11+
beforeEach(() => {
12+
return mock.createServer().then(server => {
13+
test.server = server;
14+
});
15+
});
16+
17+
it('should include `afterClusterTime` in read command with causal consistency', {
18+
metadata: { requires: { topology: 'single' } },
19+
20+
test: function() {
21+
let findCommand;
22+
let insertOperationTime = Timestamp.fromNumber(Date.now());
23+
test.server.setMessageHandler(request => {
24+
const doc = request.document;
25+
if (doc.ismaster) {
26+
request.reply(mock.DEFAULT_ISMASTER_36);
27+
} else if (doc.insert) {
28+
request.reply({ ok: 1, operationTime: insertOperationTime });
29+
} else if (doc.find) {
30+
findCommand = doc;
31+
request.reply({ ok: 1 });
32+
} else if (doc.endSessions) {
33+
request.reply({ ok: 1 });
34+
}
35+
});
36+
37+
return MongoClient.connect(`mongodb://${test.server.uri()}/test`).then(client => {
38+
const session = client.startSession({ causalConsistency: true });
39+
const coll = client.db('foo').collection('bar');
40+
41+
return coll
42+
.insert({ a: 42 }, { session: session })
43+
.then(() =>
44+
coll.findOne({}, null, { session: session, readConcern: { level: 'majoroy' } })
45+
)
46+
.then(() => {
47+
expect(findCommand.readConcern).to.have.keys(['level', 'afterClusterTime']);
48+
expect(findCommand.readConcern.afterClusterTime).to.eql(insertOperationTime);
49+
return client.close();
50+
});
51+
});
52+
}
53+
});
54+
});
55+
});

0 commit comments

Comments
 (0)