mongodb 3.5.3 → 3.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HISTORY.md +60 -0
- package/README.md +1 -1
- package/lib/change_stream.js +12 -13
- package/lib/cmap/connection_pool.js +1 -1
- package/lib/collection.js +1 -1
- package/lib/core/cursor.js +0 -9
- package/lib/core/sdam/server.js +4 -2
- package/lib/core/sdam/server_selection.js +4 -0
- package/lib/core/sdam/topology.js +37 -31
- package/lib/core/sdam/topology_description.js +27 -5
- package/lib/core/sessions.js +18 -8
- package/lib/core/topologies/shared.js +9 -2
- package/lib/core/uri_parser.js +3 -3
- package/lib/core/utils.js +4 -1
- package/lib/cursor.js +88 -19
- package/lib/mongo_client.js +62 -19
- package/lib/operations/connect.js +1 -26
- package/lib/operations/count.js +0 -4
- package/lib/operations/cursor_ops.js +1 -72
- package/lib/operations/db_ops.js +0 -361
- package/lib/operations/execute_operation.js +2 -6
- package/lib/operations/find.js +1 -2
- package/lib/operations/operation.js +1 -3
- package/lib/operations/remove_user.js +1 -1
- package/lib/utils.js +43 -1
- package/package.json +5 -5
- package/lib/operations/close.js +0 -50
- package/lib/operations/explain.js +0 -23
- package/lib/operations/has_next.js +0 -40
- package/lib/operations/next.js +0 -32
- package/lib/operations/to_array.js +0 -66
package/HISTORY.md
CHANGED
|
@@ -2,6 +2,66 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
<a name="3.5.7"></a>
|
|
6
|
+
## [3.5.7](https://github.com/mongodb/node-mongodb-native/compare/v3.5.6...v3.5.7) (2020-04-29)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* limit growth of server sessions through lazy acquisition ([3d05a6d](https://github.com/mongodb/node-mongodb-native/commit/3d05a6d))
|
|
12
|
+
* remove circular dependency warnings on node 14 ([56a1b8a](https://github.com/mongodb/node-mongodb-native/commit/56a1b8a))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
<a name="3.5.6"></a>
|
|
17
|
+
## [3.5.6](https://github.com/mongodb/node-mongodb-native/compare/v3.5.5...v3.5.6) (2020-04-14)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* always return empty array for selection on unknown topology ([f9e786a](https://github.com/mongodb/node-mongodb-native/commit/f9e786a))
|
|
23
|
+
* createCollection only uses listCollections in strict mode ([d368f12](https://github.com/mongodb/node-mongodb-native/commit/d368f12))
|
|
24
|
+
* don't throw if `withTransaction()` callback rejects with a null reason ([153646c](https://github.com/mongodb/node-mongodb-native/commit/153646c))
|
|
25
|
+
* only mark server session dirty if the client session is alive ([611be8d](https://github.com/mongodb/node-mongodb-native/commit/611be8d))
|
|
26
|
+
* polyfill for util.promisify ([1c4cf6c](https://github.com/mongodb/node-mongodb-native/commit/1c4cf6c))
|
|
27
|
+
* single `readPreferenceTags` should be parsed as an array ([a50611b](https://github.com/mongodb/node-mongodb-native/commit/a50611b))
|
|
28
|
+
* **cursor:** transforms should only be applied once to documents ([704f30a](https://github.com/mongodb/node-mongodb-native/commit/704f30a))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<a name="3.5.5"></a>
|
|
33
|
+
## [3.5.5](https://github.com/mongodb/node-mongodb-native/compare/v3.5.4...v3.5.5) (2020-03-11)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
### Bug Fixes
|
|
37
|
+
|
|
38
|
+
* correctly use template string for connection string error message ([6238c84](https://github.com/mongodb/node-mongodb-native/commit/6238c84))
|
|
39
|
+
* don't depend on private node api for `Timeout` wrapper ([3ddaa3e](https://github.com/mongodb/node-mongodb-native/commit/3ddaa3e))
|
|
40
|
+
* multiple concurrent attempts to process the queue may fail ([f69f51c](https://github.com/mongodb/node-mongodb-native/commit/f69f51c))
|
|
41
|
+
* pass optional promise lib to maybePromise ([cde11ec](https://github.com/mongodb/node-mongodb-native/commit/cde11ec))
|
|
42
|
+
* **cursor:** hasNext consumes documents on cursor with limit ([ef04d00](https://github.com/mongodb/node-mongodb-native/commit/ef04d00))
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<a name="3.5.4"></a>
|
|
47
|
+
## [3.5.4](https://github.com/mongodb/node-mongodb-native/compare/v3.5.3...v3.5.4) (2020-02-25)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
### Bug Fixes
|
|
51
|
+
|
|
52
|
+
* **cmap:** don't run min connection thread if no minimum specified ([2d1b713](https://github.com/mongodb/node-mongodb-native/commit/2d1b713))
|
|
53
|
+
* **sdam:** use ObjectId comparison to track maxElectionId ([a1e0849](https://github.com/mongodb/node-mongodb-native/commit/a1e0849))
|
|
54
|
+
* **topology:** ensure selection wait queue is always processed ([bf701d6](https://github.com/mongodb/node-mongodb-native/commit/bf701d6))
|
|
55
|
+
* **topology:** enter `STATE_CLOSING` before draining waitQueue ([494dffb](https://github.com/mongodb/node-mongodb-native/commit/494dffb))
|
|
56
|
+
* don't consume first document when calling `hasNext` on cursor ([bb359a1](https://github.com/mongodb/node-mongodb-native/commit/bb359a1))
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
### Features
|
|
60
|
+
|
|
61
|
+
* add utility helper for returning promises or using callbacks ([ac9e4c9](https://github.com/mongodb/node-mongodb-native/commit/ac9e4c9))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
5
65
|
<a name="3.5.3"></a>
|
|
6
66
|
## [3.5.3](https://github.com/mongodb/node-mongodb-native/compare/v3.5.2...v3.5.3) (2020-02-12)
|
|
7
67
|
|
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ Core Server (i.e. SERVER) project are **public**.
|
|
|
33
33
|
|
|
34
34
|
### Support / Feedback
|
|
35
35
|
|
|
36
|
-
For issues with, questions about, or feedback for the Node.js driver, please look into our [support channels](
|
|
36
|
+
For issues with, questions about, or feedback for the Node.js driver, please look into our [support channels](https://docs.mongodb.com/manual/support). Please do not email any of the driver developers directly with issues or questions - you're more likely to get an answer on the [MongoDB Community Forums](https://community.mongodb.com/tags/c/drivers-odms-connectors/7/node-js-driver).
|
|
37
37
|
|
|
38
38
|
### Change Log
|
|
39
39
|
|
package/lib/change_stream.js
CHANGED
|
@@ -6,6 +6,7 @@ const MongoError = require('./core').MongoError;
|
|
|
6
6
|
const Cursor = require('./cursor');
|
|
7
7
|
const relayEvents = require('./core/utils').relayEvents;
|
|
8
8
|
const maxWireVersion = require('./core/utils').maxWireVersion;
|
|
9
|
+
const maybePromise = require('./utils').maybePromise;
|
|
9
10
|
const AggregateOperation = require('./operations/aggregate');
|
|
10
11
|
|
|
11
12
|
const CHANGE_STREAM_OPTIONS = ['resumeAfter', 'startAfter', 'startAtOperationTime', 'fullDocument'];
|
|
@@ -124,10 +125,10 @@ class ChangeStream extends EventEmitter {
|
|
|
124
125
|
* @function ChangeStream.prototype.hasNext
|
|
125
126
|
* @param {ChangeStream~resultCallback} [callback] The result callback.
|
|
126
127
|
* @throws {MongoError}
|
|
127
|
-
* @
|
|
128
|
+
* @returns {Promise|void} returns Promise if no callback passed
|
|
128
129
|
*/
|
|
129
130
|
hasNext(callback) {
|
|
130
|
-
return this.cursor.hasNext(
|
|
131
|
+
return maybePromise(this.parent, callback, cb => this.cursor.hasNext(cb));
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
/**
|
|
@@ -135,19 +136,17 @@ class ChangeStream extends EventEmitter {
|
|
|
135
136
|
* @function ChangeStream.prototype.next
|
|
136
137
|
* @param {ChangeStream~resultCallback} [callback] The result callback.
|
|
137
138
|
* @throws {MongoError}
|
|
138
|
-
* @
|
|
139
|
+
* @returns {Promise|void} returns Promise if no callback passed
|
|
139
140
|
*/
|
|
140
141
|
next(callback) {
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
.then(change => processNewChange({ changeStream: self, change, callback }))
|
|
150
|
-
.catch(error => processNewChange({ changeStream: self, error, callback }));
|
|
142
|
+
return maybePromise(this.parent, callback, cb => {
|
|
143
|
+
if (this.isClosed()) {
|
|
144
|
+
return cb(new Error('Change Stream is not open.'));
|
|
145
|
+
}
|
|
146
|
+
this.cursor.next((error, change) => {
|
|
147
|
+
processNewChange({ changeStream: this, error, change, callback: cb });
|
|
148
|
+
});
|
|
149
|
+
});
|
|
151
150
|
}
|
|
152
151
|
|
|
153
152
|
/**
|
package/lib/collection.js
CHANGED
|
@@ -310,7 +310,7 @@ const DEPRECATED_FIND_OPTIONS = ['maxScan', 'fields', 'snapshot'];
|
|
|
310
310
|
* @param {(ReadPreference|string)} [options.readPreference] The preferred read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
|
311
311
|
* @param {boolean} [options.partial=false] Specify if the cursor should return partial results when querying against a sharded system
|
|
312
312
|
* @param {number} [options.maxTimeMS] Number of milliseconds to wait before aborting the query.
|
|
313
|
-
* @param {number} [options.maxAwaitTimeMS] The maximum amount of time for the server to wait on new documents to satisfy a tailable cursor query. Requires `
|
|
313
|
+
* @param {number} [options.maxAwaitTimeMS] The maximum amount of time for the server to wait on new documents to satisfy a tailable cursor query. Requires `tailable` and `awaitData` to be true
|
|
314
314
|
* @param {boolean} [options.noCursorTimeout] The server normally times out idle cursors after an inactivity period (10 minutes) to prevent excess memory use. Set this option to prevent that.
|
|
315
315
|
* @param {object} [options.collation] Specify collation (MongoDB 3.4 or higher) settings for update operation (see 3.4 documentation for available fields).
|
|
316
316
|
* @param {ClientSession} [options.session] optional session to use for this operation
|
package/lib/core/cursor.js
CHANGED
|
@@ -359,15 +359,6 @@ class CoreCursor extends Readable {
|
|
|
359
359
|
return this.push(this.cursorState.streamOptions.transform(result));
|
|
360
360
|
}
|
|
361
361
|
|
|
362
|
-
// If we provided a map function
|
|
363
|
-
if (
|
|
364
|
-
this.cursorState.transforms &&
|
|
365
|
-
typeof this.cursorState.transforms.doc === 'function' &&
|
|
366
|
-
result != null
|
|
367
|
-
) {
|
|
368
|
-
return this.push(this.cursorState.transforms.doc(result));
|
|
369
|
-
}
|
|
370
|
-
|
|
371
362
|
// Return the result
|
|
372
363
|
this.push(result);
|
|
373
364
|
|
package/lib/core/sdam/server.js
CHANGED
|
@@ -463,11 +463,13 @@ function markServerUnknown(server, error) {
|
|
|
463
463
|
}
|
|
464
464
|
|
|
465
465
|
function makeOperationHandler(server, options, callback) {
|
|
466
|
+
const session = options && options.session;
|
|
467
|
+
|
|
466
468
|
return function handleOperationResult(err, result) {
|
|
467
469
|
if (err) {
|
|
468
470
|
if (err instanceof MongoNetworkError) {
|
|
469
|
-
if (
|
|
470
|
-
|
|
471
|
+
if (session && !session.hasEnded) {
|
|
472
|
+
session.serverSession.isDirty = true;
|
|
471
473
|
}
|
|
472
474
|
|
|
473
475
|
if (!isNetworkTimeoutError(err)) {
|
|
@@ -186,6 +186,10 @@ function readPreferenceServerSelector(readPreference) {
|
|
|
186
186
|
);
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
if (topologyDescription.type === TopologyType.Unknown) {
|
|
190
|
+
return [];
|
|
191
|
+
}
|
|
192
|
+
|
|
189
193
|
if (
|
|
190
194
|
topologyDescription.type === TopologyType.Single ||
|
|
191
195
|
topologyDescription.type === TopologyType.Sharded
|
|
@@ -312,7 +312,7 @@ class Topology extends EventEmitter {
|
|
|
312
312
|
}
|
|
313
313
|
|
|
314
314
|
options = options || {};
|
|
315
|
-
if (this.s.state === STATE_CLOSED) {
|
|
315
|
+
if (this.s.state === STATE_CLOSED || this.s.state === STATE_CLOSING) {
|
|
316
316
|
if (typeof callback === 'function') {
|
|
317
317
|
callback();
|
|
318
318
|
}
|
|
@@ -320,6 +320,8 @@ class Topology extends EventEmitter {
|
|
|
320
320
|
return;
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
+
stateTransition(this, STATE_CLOSING);
|
|
324
|
+
|
|
323
325
|
drainWaitQueue(this[kWaitQueue], new MongoError('Topology closed'));
|
|
324
326
|
drainTimerQueue(this.s.connectionTimers);
|
|
325
327
|
|
|
@@ -336,8 +338,6 @@ class Topology extends EventEmitter {
|
|
|
336
338
|
delete this.s.detectTopologyDescriptionChange;
|
|
337
339
|
}
|
|
338
340
|
|
|
339
|
-
stateTransition(this, STATE_CLOSING);
|
|
340
|
-
|
|
341
341
|
this.s.sessions.forEach(session => session.endSession());
|
|
342
342
|
this.s.sessionPool.endAllPooledSessions(() => {
|
|
343
343
|
eachAsync(
|
|
@@ -378,6 +378,8 @@ class Topology extends EventEmitter {
|
|
|
378
378
|
let readPreference;
|
|
379
379
|
if (selector instanceof ReadPreference) {
|
|
380
380
|
readPreference = selector;
|
|
381
|
+
} else if (typeof selector === 'string') {
|
|
382
|
+
readPreference = new ReadPreference(selector);
|
|
381
383
|
} else {
|
|
382
384
|
translateReadPreference(options);
|
|
383
385
|
readPreference = options.readPreference || ReadPreference.primary;
|
|
@@ -434,8 +436,7 @@ class Topology extends EventEmitter {
|
|
|
434
436
|
}, serverSelectionTimeoutMS);
|
|
435
437
|
}
|
|
436
438
|
|
|
437
|
-
|
|
438
|
-
this[kWaitQueue].unshift(waitQueueMember);
|
|
439
|
+
this[kWaitQueue].push(waitQueueMember);
|
|
439
440
|
processWaitQueue(this);
|
|
440
441
|
}
|
|
441
442
|
|
|
@@ -520,10 +521,10 @@ class Topology extends EventEmitter {
|
|
|
520
521
|
}
|
|
521
522
|
|
|
522
523
|
// If we already know all the information contained in this updated description, then
|
|
523
|
-
// we don't need to update
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
524
|
+
// we don't need to emit SDAM events, but still need to update the description, in order
|
|
525
|
+
// to keep client-tracked attributes like last update time and round trip time up to date
|
|
526
|
+
const equalDescriptions =
|
|
527
|
+
previousServerDescription && previousServerDescription.equals(serverDescription);
|
|
527
528
|
|
|
528
529
|
// first update the TopologyDescription
|
|
529
530
|
this.s.description = this.s.description.update(serverDescription);
|
|
@@ -533,15 +534,17 @@ class Topology extends EventEmitter {
|
|
|
533
534
|
}
|
|
534
535
|
|
|
535
536
|
// emit monitoring events for this change
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
537
|
+
if (!equalDescriptions) {
|
|
538
|
+
this.emit(
|
|
539
|
+
'serverDescriptionChanged',
|
|
540
|
+
new events.ServerDescriptionChangedEvent(
|
|
541
|
+
this.s.id,
|
|
542
|
+
serverDescription.address,
|
|
543
|
+
previousServerDescription,
|
|
544
|
+
this.s.description.servers.get(serverDescription.address)
|
|
545
|
+
)
|
|
546
|
+
);
|
|
547
|
+
}
|
|
545
548
|
|
|
546
549
|
// update server list from updated descriptions
|
|
547
550
|
updateServers(this, serverDescription);
|
|
@@ -551,14 +554,16 @@ class Topology extends EventEmitter {
|
|
|
551
554
|
processWaitQueue(this);
|
|
552
555
|
}
|
|
553
556
|
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
557
|
+
if (!equalDescriptions) {
|
|
558
|
+
this.emit(
|
|
559
|
+
'topologyDescriptionChanged',
|
|
560
|
+
new events.TopologyDescriptionChangedEvent(
|
|
561
|
+
this.s.id,
|
|
562
|
+
previousTopologyDescription,
|
|
563
|
+
this.s.description
|
|
564
|
+
)
|
|
565
|
+
);
|
|
566
|
+
}
|
|
562
567
|
}
|
|
563
568
|
|
|
564
569
|
auth(credentials, callback) {
|
|
@@ -980,7 +985,7 @@ function srvPollingHandler(topology) {
|
|
|
980
985
|
|
|
981
986
|
function drainWaitQueue(queue, err) {
|
|
982
987
|
while (queue.length) {
|
|
983
|
-
const waitQueueMember = queue.
|
|
988
|
+
const waitQueueMember = queue.shift();
|
|
984
989
|
clearTimeout(waitQueueMember.timer);
|
|
985
990
|
if (!waitQueueMember[kCancelled]) {
|
|
986
991
|
waitQueueMember.callback(err);
|
|
@@ -994,9 +999,9 @@ function processWaitQueue(topology) {
|
|
|
994
999
|
return;
|
|
995
1000
|
}
|
|
996
1001
|
|
|
997
|
-
const isSharded = topology.description.type === TopologyType.Sharded;
|
|
998
1002
|
const serverDescriptions = Array.from(topology.description.servers.values());
|
|
999
|
-
|
|
1003
|
+
const membersToProcess = topology[kWaitQueue].length;
|
|
1004
|
+
for (let i = 0; i < membersToProcess && topology[kWaitQueue].length; ++i) {
|
|
1000
1005
|
const waitQueueMember = topology[kWaitQueue].shift();
|
|
1001
1006
|
if (waitQueueMember[kCancelled]) {
|
|
1002
1007
|
continue;
|
|
@@ -1011,17 +1016,18 @@ function processWaitQueue(topology) {
|
|
|
1011
1016
|
} catch (e) {
|
|
1012
1017
|
clearTimeout(waitQueueMember.timer);
|
|
1013
1018
|
waitQueueMember.callback(e);
|
|
1014
|
-
|
|
1019
|
+
continue;
|
|
1015
1020
|
}
|
|
1016
1021
|
|
|
1017
1022
|
if (selectedDescriptions.length === 0) {
|
|
1018
1023
|
topology[kWaitQueue].push(waitQueueMember);
|
|
1019
|
-
|
|
1024
|
+
continue;
|
|
1020
1025
|
}
|
|
1021
1026
|
|
|
1022
1027
|
const selectedServerDescription = randomSelection(selectedDescriptions);
|
|
1023
1028
|
const selectedServer = topology.s.servers.get(selectedServerDescription.address);
|
|
1024
1029
|
const transaction = waitQueueMember.transaction;
|
|
1030
|
+
const isSharded = topology.description.type === TopologyType.Sharded;
|
|
1025
1031
|
if (isSharded && transaction && transaction.isActive) {
|
|
1026
1032
|
transaction.pinServer(selectedServer);
|
|
1027
1033
|
}
|
|
@@ -279,6 +279,26 @@ function topologyTypeForServerType(serverType) {
|
|
|
279
279
|
return TopologyType.ReplicaSetNoPrimary;
|
|
280
280
|
}
|
|
281
281
|
|
|
282
|
+
function compareObjectId(oid1, oid2) {
|
|
283
|
+
if (oid1 == null) {
|
|
284
|
+
return -1;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (oid2 == null) {
|
|
288
|
+
return 1;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (oid1.id instanceof Buffer && oid2.id instanceof Buffer) {
|
|
292
|
+
const oid1Buffer = oid1.id;
|
|
293
|
+
const oid2Buffer = oid2.id;
|
|
294
|
+
return oid1Buffer.compare(oid2Buffer);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const oid1String = oid1.toString();
|
|
298
|
+
const oid2String = oid2.toString();
|
|
299
|
+
return oid1String.localeCompare(oid2String);
|
|
300
|
+
}
|
|
301
|
+
|
|
282
302
|
function updateRsFromPrimary(
|
|
283
303
|
serverDescriptions,
|
|
284
304
|
setName,
|
|
@@ -292,11 +312,13 @@ function updateRsFromPrimary(
|
|
|
292
312
|
return [checkHasPrimary(serverDescriptions), setName, maxSetVersion, maxElectionId];
|
|
293
313
|
}
|
|
294
314
|
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
315
|
+
const electionId = serverDescription.electionId ? serverDescription.electionId : null;
|
|
316
|
+
if (serverDescription.setVersion && electionId) {
|
|
317
|
+
if (maxSetVersion && maxElectionId) {
|
|
318
|
+
if (
|
|
319
|
+
maxSetVersion > serverDescription.setVersion ||
|
|
320
|
+
compareObjectId(maxElectionId, electionId) > 0
|
|
321
|
+
) {
|
|
300
322
|
// this primary is stale, we must remove it
|
|
301
323
|
serverDescriptions.set(
|
|
302
324
|
serverDescription.address,
|
package/lib/core/sessions.js
CHANGED
|
@@ -46,6 +46,8 @@ function assertAlive(session, callback) {
|
|
|
46
46
|
* @typedef {Object} SessionId
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
|
+
const kServerSession = Symbol('serverSession');
|
|
50
|
+
|
|
49
51
|
/**
|
|
50
52
|
* A class representing a client session on the server
|
|
51
53
|
* WARNING: not meant to be instantiated directly.
|
|
@@ -79,8 +81,8 @@ class ClientSession extends EventEmitter {
|
|
|
79
81
|
this.topology = topology;
|
|
80
82
|
this.sessionPool = sessionPool;
|
|
81
83
|
this.hasEnded = false;
|
|
82
|
-
this.serverSession = sessionPool.acquire();
|
|
83
84
|
this.clientOptions = clientOptions;
|
|
85
|
+
this[kServerSession] = undefined;
|
|
84
86
|
|
|
85
87
|
this.supports = {
|
|
86
88
|
causalConsistency:
|
|
@@ -104,6 +106,14 @@ class ClientSession extends EventEmitter {
|
|
|
104
106
|
return this.serverSession.id;
|
|
105
107
|
}
|
|
106
108
|
|
|
109
|
+
get serverSession() {
|
|
110
|
+
if (this[kServerSession] == null) {
|
|
111
|
+
this[kServerSession] = this.sessionPool.acquire();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return this[kServerSession];
|
|
115
|
+
}
|
|
116
|
+
|
|
107
117
|
/**
|
|
108
118
|
* Ends this session on the server
|
|
109
119
|
*
|
|
@@ -123,14 +133,14 @@ class ClientSession extends EventEmitter {
|
|
|
123
133
|
this.abortTransaction(); // pass in callback?
|
|
124
134
|
}
|
|
125
135
|
|
|
136
|
+
// release the server session back to the pool
|
|
137
|
+
this.sessionPool.release(this.serverSession);
|
|
138
|
+
this[kServerSession] = undefined;
|
|
139
|
+
|
|
126
140
|
// mark the session as ended, and emit a signal
|
|
127
141
|
this.hasEnded = true;
|
|
128
142
|
this.emit('ended', this);
|
|
129
143
|
|
|
130
|
-
// release the server session back to the pool
|
|
131
|
-
this.sessionPool.release(this.serverSession);
|
|
132
|
-
this.serverSession = null;
|
|
133
|
-
|
|
134
144
|
// spec indicates that we should ignore all errors for `endSessions`
|
|
135
145
|
if (typeof callback === 'function') callback(null, null);
|
|
136
146
|
}
|
|
@@ -304,6 +314,7 @@ function isUnknownTransactionCommitResult(err) {
|
|
|
304
314
|
}
|
|
305
315
|
|
|
306
316
|
function isMaxTimeMSExpiredError(err) {
|
|
317
|
+
if (err == null) return false;
|
|
307
318
|
return (
|
|
308
319
|
err.code === MAX_TIME_MS_EXPIRED_CODE ||
|
|
309
320
|
(err.writeConcernError && err.writeConcernError.code === MAX_TIME_MS_EXPIRED_CODE)
|
|
@@ -691,13 +702,12 @@ function commandSupportsReadConcern(command, options) {
|
|
|
691
702
|
* @return {MongoError|null} An error, if some error condition was met
|
|
692
703
|
*/
|
|
693
704
|
function applySession(session, command, options) {
|
|
694
|
-
|
|
695
|
-
if (serverSession == null) {
|
|
705
|
+
if (session.hasEnded) {
|
|
696
706
|
// TODO: merge this with `assertAlive`, did not want to throw a try/catch here
|
|
697
707
|
return new MongoError('Cannot use a session that has ended');
|
|
698
708
|
}
|
|
699
709
|
|
|
700
|
-
|
|
710
|
+
const serverSession = session.serverSession;
|
|
701
711
|
serverSession.lastUse = Date.now();
|
|
702
712
|
command.lsid = serverSession.id;
|
|
703
713
|
|
|
@@ -211,10 +211,18 @@ function Interval(fn, time) {
|
|
|
211
211
|
|
|
212
212
|
function Timeout(fn, time) {
|
|
213
213
|
var timer = false;
|
|
214
|
+
var func = () => {
|
|
215
|
+
if (timer) {
|
|
216
|
+
clearTimeout(timer);
|
|
217
|
+
timer = false;
|
|
218
|
+
|
|
219
|
+
fn();
|
|
220
|
+
}
|
|
221
|
+
};
|
|
214
222
|
|
|
215
223
|
this.start = function() {
|
|
216
224
|
if (!this.isRunning()) {
|
|
217
|
-
timer = setTimeout(
|
|
225
|
+
timer = setTimeout(func, time);
|
|
218
226
|
}
|
|
219
227
|
return this;
|
|
220
228
|
};
|
|
@@ -226,7 +234,6 @@ function Timeout(fn, time) {
|
|
|
226
234
|
};
|
|
227
235
|
|
|
228
236
|
this.isRunning = function() {
|
|
229
|
-
if (timer && timer._called) return false;
|
|
230
237
|
return timer !== false;
|
|
231
238
|
};
|
|
232
239
|
}
|
package/lib/core/uri_parser.js
CHANGED
|
@@ -285,8 +285,8 @@ function applyConnectionStringOption(obj, key, value, options) {
|
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
287
|
|
|
288
|
-
if (key === 'readpreferencetags'
|
|
289
|
-
value = splitArrayOfMultipleReadPreferenceTags(value);
|
|
288
|
+
if (key === 'readpreferencetags') {
|
|
289
|
+
value = Array.isArray(value) ? splitArrayOfMultipleReadPreferenceTags(value) : [value];
|
|
290
290
|
}
|
|
291
291
|
|
|
292
292
|
// set the actual value
|
|
@@ -510,7 +510,7 @@ function assertTlsOptionsAreEqual(optionName, queryString, queryStringKeys) {
|
|
|
510
510
|
const firstValue = queryString[optionName][0];
|
|
511
511
|
queryString[optionName].forEach(tlsValue => {
|
|
512
512
|
if (tlsValue !== firstValue) {
|
|
513
|
-
throw new MongoParseError(
|
|
513
|
+
throw new MongoParseError(`All values of ${optionName} must be the same.`);
|
|
514
514
|
}
|
|
515
515
|
});
|
|
516
516
|
}
|
package/lib/core/utils.js
CHANGED
|
@@ -255,6 +255,8 @@ function makeClientMetadata(options) {
|
|
|
255
255
|
return metadata;
|
|
256
256
|
}
|
|
257
257
|
|
|
258
|
+
const noop = () => {};
|
|
259
|
+
|
|
258
260
|
module.exports = {
|
|
259
261
|
uuidV4,
|
|
260
262
|
calculateDurationInMs,
|
|
@@ -270,5 +272,6 @@ module.exports = {
|
|
|
270
272
|
tagsStrictEqual,
|
|
271
273
|
errorStrictEqual,
|
|
272
274
|
makeStateMachine,
|
|
273
|
-
makeClientMetadata
|
|
275
|
+
makeClientMetadata,
|
|
276
|
+
noop
|
|
274
277
|
};
|