Skip to content

Commit 79f33ca

Browse files
committed
feat(unified-sdam): backport unified SDAM to master for v3.2.0
1 parent d8aed2b commit 79f33ca

37 files changed

+325
-121
lines changed

lib/operations/mongo_client_ops.js

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const ReadPreference = require('mongodb-core').ReadPreference;
1111
const ReplSet = require('../topologies/replset');
1212
const Server = require('../topologies/server');
1313
const ServerSessionPool = require('mongodb-core').Sessions.ServerSessionPool;
14+
const NativeTopology = require('../topologies/native_topology');
1415

1516
let client;
1617
function loadClient() {
@@ -109,7 +110,9 @@ const validOptionNames = [
109110
'minSize',
110111
'monitorCommands',
111112
'retryWrites',
112-
'useNewUrlParser'
113+
'useNewUrlParser',
114+
'useUnifiedTopology',
115+
'serverSelectionTimeoutMS'
113116
];
114117

115118
function addListeners(mongoClient, topology) {
@@ -126,7 +129,10 @@ function addListeners(mongoClient, topology) {
126129

127130
function assignTopology(client, topology) {
128131
client.topology = topology;
129-
topology.s.sessionPool = new ServerSessionPool(topology.s.coreTopology);
132+
topology.s.sessionPool =
133+
topology instanceof NativeTopology
134+
? new ServerSessionPool(topology)
135+
: new ServerSessionPool(topology.s.coreTopology);
130136
}
131137

132138
// Clear out all events
@@ -225,6 +231,15 @@ function connect(mongoClient, url, options, callback) {
225231
}
226232
}
227233

234+
if (_finalOptions.useUnifiedTopology) {
235+
return createTopology(
236+
mongoClient,
237+
'unified',
238+
_finalOptions,
239+
connectHandler(mongoClient, _finalOptions, connectCallback)
240+
);
241+
}
242+
228243
// Do we have a replicaset then skip discovery and go straight to connectivity
229244
if (_finalOptions.replicaSet || _finalOptions.rs_name) {
230245
return createTopology(
@@ -434,6 +449,8 @@ function createTopology(mongoClient, topologyType, options, callback) {
434449
topology = new Mongos(servers, options);
435450
} else if (topologyType === 'replicaset') {
436451
topology = new ReplSet(servers, options);
452+
} else if (topologyType === 'unified') {
453+
topology = new NativeTopology(options.servers, options);
437454
}
438455

439456
// Add listeners

lib/topologies/native_topology.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
'use strict';
2+
3+
const Topology = require('mongodb-core').Topology;
4+
const ServerCapabilities = require('./topology_base').ServerCapabilities;
5+
const Cursor = require('../cursor');
6+
const translateOptions = require('../utils').translateOptions;
7+
8+
class NativeTopology extends Topology {
9+
constructor(servers, options) {
10+
options = options || {};
11+
12+
let clonedOptions = Object.assign(
13+
{},
14+
{
15+
cursorFactory: Cursor,
16+
reconnect: false,
17+
emitError: options.emitError,
18+
size: options.poolSize,
19+
monitorCommands: options.monitorCommands
20+
}
21+
);
22+
23+
// Translate any SSL options and other connectivity options
24+
clonedOptions = translateOptions(clonedOptions, options);
25+
26+
// Socket options
27+
var socketOptions =
28+
options.socketOptions && Object.keys(options.socketOptions).length > 0
29+
? options.socketOptions
30+
: options;
31+
32+
// Translate all the options to the mongodb-core ones
33+
clonedOptions = translateOptions(clonedOptions, socketOptions);
34+
35+
super(servers, clonedOptions);
36+
37+
// Do we have an application specific string
38+
if (options.appname) {
39+
this.s.clientInfo.application = { name: options.appname };
40+
}
41+
}
42+
43+
capabilities() {
44+
if (this.s.sCapabilities) return this.s.sCapabilities;
45+
if (this.lastIsMaster() == null) return null;
46+
this.s.sCapabilities = new ServerCapabilities(this.lastIsMaster());
47+
return this.s.sCapabilities;
48+
}
49+
}
50+
51+
module.exports = NativeTopology;

lib/utils.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,12 +588,12 @@ function decorateWithCollation(command, target, options) {
588588
throw new TypeError('parameter "target" is missing a topology');
589589
}
590590

591-
const capabilities = target.s.topology.capabilities();
591+
const capabilities = topology.capabilities();
592592
if (options.collation && typeof options.collation === 'object') {
593593
if (capabilities && capabilities.commandsTakeCollation) {
594594
command.collation = options.collation;
595595
} else {
596-
throw new MongoError(`server ${topology.s.coreTopology.name} does not support collation`);
596+
throw new MongoError(`Current topology does not support collation`);
597597
}
598598
}
599599
}

test/config.js

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,26 @@ const f = require('util').format;
44
const url = require('url');
55
const qs = require('querystring');
66
class NativeConfiguration extends ConfigurationBase {
7-
constructor(options) {
8-
super(options);
7+
constructor(environment) {
8+
super(environment);
99

1010
this.type = 'native';
11-
this.topology = options.topology || this.defaultTopology;
12-
this.replicasetName = options.replicasetName || 'rs';
11+
this.topology = environment.topology || this.defaultTopology;
12+
this.environment = environment;
13+
14+
if (environment.setName) {
15+
this.replicasetName = environment.setName || 'rs';
16+
}
1317
}
1418

1519
defaultTopology(serverHost, serverPort, serverOpts, _mongo) {
1620
return new _mongo.Server(serverHost, serverPort, serverOpts || {});
1721
}
1822

23+
usingUnifiedTopology() {
24+
return !!process.env.MONGODB_UNIFIED_TOPOLOGY;
25+
}
26+
1927
start(callback) {
2028
const self = this;
2129
if (this.skipStart) return callback();
@@ -50,11 +58,20 @@ class NativeConfiguration extends ConfigurationBase {
5058
newClient(dbOptions, serverOptions) {
5159
// support MongoClient contructor form (url, options) for `newClient`
5260
if (typeof dbOptions === 'string') {
53-
return new this.mongo.MongoClient(dbOptions, serverOptions);
61+
return new this.mongo.MongoClient(
62+
dbOptions,
63+
this.usingUnifiedTopology()
64+
? Object.assign(
65+
{ useUnifiedTopology: true, serverSelectionTimeoutMS: 1000 },
66+
serverOptions
67+
)
68+
: serverOptions
69+
);
5470
}
5571

5672
dbOptions = dbOptions || {};
5773
serverOptions = Object.assign({}, { haInterval: 100 }, serverOptions);
74+
if (this.usingUnifiedTopology()) serverOptions.useUnifiedTopology = true;
5875

5976
// Override implementation
6077
if (this.options.newDbInstance) {

test/examples/aggregate.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
/* eslint-disable no-unused-vars */
33

44
const setupDatabase = require('../functional/shared').setupDatabase;
5-
const MongoClient = require('../../lib/mongo_client');
65

76
describe('examples.aggregaton:', function() {
87
let client;
@@ -13,7 +12,7 @@ describe('examples.aggregaton:', function() {
1312
});
1413

1514
beforeEach(async function() {
16-
client = await MongoClient.connect(this.configuration.url());
15+
client = await this.configuration.newClient().connect();
1716
collection = client.db(this.configuration.db).collection('aggregateExample');
1817
});
1918

test/examples/array_filters.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
const setupDatabase = require('../functional/shared').setupDatabase;
4-
const MongoClient = require('../../lib/mongo_client');
54

65
describe('examples(project-fields-from-query):', function() {
76
let client;
@@ -12,7 +11,7 @@ describe('examples(project-fields-from-query):', function() {
1211
});
1312

1413
beforeEach(async function() {
15-
client = await MongoClient.connect(this.configuration.url());
14+
client = await this.configuration.newClient().connect();
1615
collection = client.db(this.configuration.db).collection('arrayFilterUpdateExample');
1716
});
1817

test/examples/causal_consistency.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const setupDatabase = require('../functional/shared').setupDatabase;
44
const expect = require('chai').expect;
5-
const MongoClient = require('../../lib/mongo_client');
65

76
describe('examples(causal-consistency):', function() {
87
let client;
@@ -14,7 +13,7 @@ describe('examples(causal-consistency):', function() {
1413
});
1514

1615
beforeEach(async function() {
17-
client = await MongoClient.connect(this.configuration.url());
16+
client = await this.configuration.newClient().connect();
1817
collection = client.db(this.configuration.db).collection('arrayFilterUpdateExample');
1918
});
2019

test/examples/change_streams.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
const setupDatabase = require('../functional/shared').setupDatabase;
55
const expect = require('chai').expect;
6-
const MongoClient = require('../../lib/mongo_client');
76

87
describe('examples(change-stream):', function() {
98
let client;
@@ -14,7 +13,7 @@ describe('examples(change-stream):', function() {
1413
});
1514

1615
beforeEach(async function() {
17-
client = await MongoClient.connect(this.configuration.url());
16+
client = await this.configuration.newClient().connect();
1817
db = client.db(this.configuration.db);
1918

2019
await db.collection('inventory').deleteMany({});

test/examples/create_index.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict';
22

33
const setupDatabase = require('../functional/shared').setupDatabase;
4-
const MongoClient = require('../../lib/mongo_client');
54

65
describe('examples.createIndex:', function() {
76
let client;
@@ -12,7 +11,7 @@ describe('examples.createIndex:', function() {
1211
});
1312

1413
beforeEach(async function() {
15-
client = await MongoClient.connect(this.configuration.url());
14+
client = await this.configuration.newClient().connect();
1615
collection = client.db(this.configuration.db).collection('createIndexExample');
1716
});
1817

test/examples/insert.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const setupDatabase = require('../functional/shared').setupDatabase;
44
const expect = require('chai').expect;
5-
const MongoClient = require('../../lib/mongo_client');
65

76
describe('examples(insert):', function() {
87
let client;
@@ -13,7 +12,7 @@ describe('examples(insert):', function() {
1312
});
1413

1514
beforeEach(async function() {
16-
client = await MongoClient.connect(this.configuration.url());
15+
client = await this.configuration.newClient().connect();
1716
db = client.db(this.configuration.db);
1817

1918
await db.collection('inventory').deleteMany({});

test/examples/project_fields_from_query_results.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const setupDatabase = require('../functional/shared').setupDatabase;
44
const expect = require('chai').expect;
5-
const MongoClient = require('../../lib/mongo_client');
65

76
describe('examples(project-fields-from-query):', function() {
87
let client;
@@ -13,7 +12,7 @@ describe('examples(project-fields-from-query):', function() {
1312
});
1413

1514
beforeEach(async function() {
16-
client = await MongoClient.connect(this.configuration.url());
15+
client = await this.configuration.newClient().connect();
1716
db = client.db(this.configuration.db);
1817

1918
await db.collection('inventory').deleteMany({});

test/examples/query.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const setupDatabase = require('../functional/shared').setupDatabase;
44
const expect = require('chai').expect;
5-
const MongoClient = require('../../lib/mongo_client');
65

76
describe('examples(query):', function() {
87
let client;
@@ -13,7 +12,7 @@ describe('examples(query):', function() {
1312
});
1413

1514
beforeEach(async function() {
16-
client = await MongoClient.connect(this.configuration.url());
15+
client = await this.configuration.newClient().connect();
1716
db = client.db(this.configuration.db);
1817

1918
await db.collection('inventory').deleteMany({});

test/examples/query_array_of_documents.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const setupDatabase = require('../functional/shared').setupDatabase;
44
const expect = require('chai').expect;
5-
const MongoClient = require('../../lib/mongo_client');
65

76
describe('examples(query-array-of-documents):', function() {
87
let client;
@@ -13,7 +12,7 @@ describe('examples(query-array-of-documents):', function() {
1312
});
1413

1514
beforeEach(async function() {
16-
client = await MongoClient.connect(this.configuration.url());
15+
client = await this.configuration.newClient().connect();
1716
db = client.db(this.configuration.db);
1817

1918
await db.collection('inventory').deleteMany({});

test/examples/query_arrays.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const setupDatabase = require('../functional/shared').setupDatabase;
44
const expect = require('chai').expect;
5-
const MongoClient = require('../../lib/mongo_client');
65

76
describe('examples(query-arrays):', function() {
87
let client;
@@ -13,7 +12,7 @@ describe('examples(query-arrays):', function() {
1312
});
1413

1514
beforeEach(async function() {
16-
client = await MongoClient.connect(this.configuration.url());
15+
client = await this.configuration.newClient().connect();
1716
db = client.db(this.configuration.db);
1817

1918
await db.collection('inventory').deleteMany({});

test/examples/query_embedded_documents.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const setupDatabase = require('../functional/shared').setupDatabase;
44
const expect = require('chai').expect;
5-
const MongoClient = require('../../lib/mongo_client');
65

76
describe('examples(query-embedded-documents):', function() {
87
let client;
@@ -13,7 +12,7 @@ describe('examples(query-embedded-documents):', function() {
1312
});
1413

1514
beforeEach(async function() {
16-
client = await MongoClient.connect(this.configuration.url());
15+
client = await this.configuration.newClient().connect();
1716
db = client.db(this.configuration.db);
1817

1918
await db.collection('inventory').deleteMany({});

test/examples/query_for_null_fields.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const setupDatabase = require('../functional/shared').setupDatabase;
44
const expect = require('chai').expect;
5-
const MongoClient = require('../../lib/mongo_client');
65

76
describe('examples(query-for-null-fields):', function() {
87
let client;
@@ -13,7 +12,7 @@ describe('examples(query-for-null-fields):', function() {
1312
});
1413

1514
beforeEach(async function() {
16-
client = await MongoClient.connect(this.configuration.url());
15+
client = await this.configuration.newClient().connect();
1716
db = client.db(this.configuration.db);
1817

1918
await db.collection('inventory').deleteMany({});

test/examples/remove_documents.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
const setupDatabase = require('../functional/shared').setupDatabase;
44
const expect = require('chai').expect;
5-
const MongoClient = require('../../lib/mongo_client');
65

76
describe('examples(remove-documents):', function() {
87
let client;
@@ -13,7 +12,7 @@ describe('examples(remove-documents):', function() {
1312
});
1413

1514
beforeEach(async function() {
16-
client = await MongoClient.connect(this.configuration.url());
15+
client = await this.configuration.newClient().connect();
1716
db = client.db(this.configuration.db);
1817

1918
await db.collection('inventory').deleteMany({});

0 commit comments

Comments
 (0)