mongodb 3.4.0 → 3.5.2
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 +72 -0
- package/index.js +1 -0
- package/lib/bulk/common.js +1 -1
- package/lib/cmap/connection.js +369 -0
- package/lib/cmap/connection_pool.js +593 -0
- package/lib/cmap/errors.js +35 -0
- package/lib/cmap/events.js +154 -0
- package/lib/{core/cmap → cmap}/message_stream.js +19 -17
- package/lib/cmap/stream_description.js +45 -0
- package/lib/core/auth/scram.js +1 -1
- package/lib/core/connection/apm.js +24 -7
- package/lib/core/connection/connect.js +55 -26
- package/lib/core/connection/pool.js +3 -16
- package/lib/core/error.js +27 -10
- package/lib/core/index.js +1 -0
- package/lib/core/sdam/events.js +124 -0
- package/lib/core/sdam/monitor.js +251 -0
- package/lib/core/sdam/server.js +148 -198
- package/lib/core/sdam/server_description.js +6 -4
- package/lib/core/sdam/server_selection.js +0 -91
- package/lib/core/sdam/topology.js +162 -136
- package/lib/core/sdam/topology_description.js +10 -8
- package/lib/core/sessions.js +16 -3
- package/lib/core/topologies/mongos.js +5 -13
- package/lib/core/topologies/replset.js +5 -10
- package/lib/core/topologies/server.js +9 -4
- package/lib/core/topologies/shared.js +0 -60
- package/lib/core/transactions.js +18 -7
- package/lib/core/uri_parser.js +3 -0
- package/lib/core/utils.js +84 -18
- package/lib/core/wireprotocol/command.js +2 -9
- package/lib/gridfs-stream/upload.js +1 -1
- package/lib/mongo_client.js +6 -6
- package/lib/operations/connect.js +118 -49
- package/lib/operations/execute_operation.js +31 -40
- package/lib/operations/find_one.js +13 -9
- package/lib/topologies/mongos.js +2 -9
- package/lib/topologies/native_topology.js +2 -6
- package/lib/topologies/replset.js +2 -9
- package/lib/topologies/server.js +2 -9
- package/lib/topologies/topology_base.js +4 -25
- package/lib/utils.js +11 -2
- package/package.json +3 -2
- package/lib/core/cmap/connection.js +0 -220
- package/lib/core/sdam/monitoring.js +0 -241
package/HISTORY.md
CHANGED
|
@@ -2,6 +2,78 @@
|
|
|
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.2"></a>
|
|
6
|
+
## [3.5.2](https://github.com/mongodb/node-mongodb-native/compare/v3.5.1...v3.5.2) (2020-01-20)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* properly handle err messages in MongoDB 2.6 servers ([0f4ab38](https://github.com/mongodb/node-mongodb-native/commit/0f4ab38))
|
|
12
|
+
* **topology:** always emit SDAM unrecoverable errors ([57f158f](https://github.com/mongodb/node-mongodb-native/commit/57f158f))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
<a name="3.5.1"></a>
|
|
17
|
+
## [3.5.1](https://github.com/mongodb/node-mongodb-native/compare/v3.5.0...v3.5.1) (2020-01-17)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Bug Fixes
|
|
21
|
+
|
|
22
|
+
* **cmap:** accept all node TLS options as pool options ([5995d1d](https://github.com/mongodb/node-mongodb-native/commit/5995d1d))
|
|
23
|
+
* **cmap:** error wait queue members on failed connection creation ([d13b153](https://github.com/mongodb/node-mongodb-native/commit/d13b153))
|
|
24
|
+
* **connect:** listen to `secureConnect` for tls connections ([f8bdb8d](https://github.com/mongodb/node-mongodb-native/commit/f8bdb8d))
|
|
25
|
+
* **transactions:** use options helper to resolve read preference ([9698a76](https://github.com/mongodb/node-mongodb-native/commit/9698a76))
|
|
26
|
+
* **uri_parser:** TLS uri variants imply `ssl=true` ([c8d182e](https://github.com/mongodb/node-mongodb-native/commit/c8d182e))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
<a name="3.5.0"></a>
|
|
31
|
+
# [3.5.0](https://github.com/mongodb/node-mongodb-native/compare/v3.4.1...v3.5.0) (2020-01-14)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
### Bug Fixes
|
|
35
|
+
|
|
36
|
+
* copy `ssl` option to pool connection options ([563ced6](https://github.com/mongodb/node-mongodb-native/commit/563ced6))
|
|
37
|
+
* destroy connections marked as closed on checkIn / checkOut ([2bd17a6](https://github.com/mongodb/node-mongodb-native/commit/2bd17a6))
|
|
38
|
+
* ensure sync errors are thrown, and don't callback twice ([cca5b49](https://github.com/mongodb/node-mongodb-native/commit/cca5b49))
|
|
39
|
+
* ignore connection errors during pool destruction ([b8805dc](https://github.com/mongodb/node-mongodb-native/commit/b8805dc))
|
|
40
|
+
* not all message payloads are arrays of Buffer ([e4df5f4](https://github.com/mongodb/node-mongodb-native/commit/e4df5f4))
|
|
41
|
+
* recover on network error during initial connect ([a13dc68](https://github.com/mongodb/node-mongodb-native/commit/a13dc68))
|
|
42
|
+
* remove servers with me mismatch in `updateRsFromPrimary` ([95a772e](https://github.com/mongodb/node-mongodb-native/commit/95a772e))
|
|
43
|
+
* report the correct platform in client metadata ([35d0274](https://github.com/mongodb/node-mongodb-native/commit/35d0274))
|
|
44
|
+
* reschedule monitoring before emitting heartbeat events ([7fcbeb5](https://github.com/mongodb/node-mongodb-native/commit/7fcbeb5))
|
|
45
|
+
* socket timeout for handshake should be `connectTimeoutMS` ([c83af9a](https://github.com/mongodb/node-mongodb-native/commit/c83af9a))
|
|
46
|
+
* timed out streams should be destroyed on `timeout` event ([5319ff9](https://github.com/mongodb/node-mongodb-native/commit/5319ff9))
|
|
47
|
+
* use remote address for stream identifier ([f13c20b](https://github.com/mongodb/node-mongodb-native/commit/f13c20b))
|
|
48
|
+
* used weighted RTT calculation for server selection ([d446be5](https://github.com/mongodb/node-mongodb-native/commit/d446be5))
|
|
49
|
+
* **execute-operation:** don't swallow synchronous errors ([0a2d4e9](https://github.com/mongodb/node-mongodb-native/commit/0a2d4e9))
|
|
50
|
+
* **gridfs:** make a copy of chunk before writing to server ([b4ec5b8](https://github.com/mongodb/node-mongodb-native/commit/b4ec5b8))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Features
|
|
54
|
+
|
|
55
|
+
* add a `withConnection` helper to the connection pool ([d59dced](https://github.com/mongodb/node-mongodb-native/commit/d59dced))
|
|
56
|
+
* include `connectionId` for APM with new CMAP connection pool ([9bd360c](https://github.com/mongodb/node-mongodb-native/commit/9bd360c))
|
|
57
|
+
* integrate CMAP connection pool into unified topology ([9dd3939](https://github.com/mongodb/node-mongodb-native/commit/9dd3939))
|
|
58
|
+
* introduce `MongoServerSelectionError` ([0cf7ec9](https://github.com/mongodb/node-mongodb-native/commit/0cf7ec9))
|
|
59
|
+
* introduce a class for tracking stream specific attributes ([f6bf82c](https://github.com/mongodb/node-mongodb-native/commit/f6bf82c))
|
|
60
|
+
* introduce a new `Monitor` type for server monitoring ([2bfe2a1](https://github.com/mongodb/node-mongodb-native/commit/2bfe2a1))
|
|
61
|
+
* relay all CMAP events to MongoClient ([1aea4de](https://github.com/mongodb/node-mongodb-native/commit/1aea4de))
|
|
62
|
+
* support socket timeouts on a per-connection level ([93e8ad0](https://github.com/mongodb/node-mongodb-native/commit/93e8ad0))
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
<a name="3.4.1"></a>
|
|
67
|
+
## [3.4.1](https://github.com/mongodb/node-mongodb-native/compare/v3.4.0...v3.4.1) (2019-12-19)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
### Bug Fixes
|
|
71
|
+
|
|
72
|
+
* **bulk:** use original indexes as map for current op index ([20800ac](https://github.com/mongodb/node-mongodb-native/commit/20800ac))
|
|
73
|
+
* always check for network errors during SCRAM conversation ([e46a70e](https://github.com/mongodb/node-mongodb-native/commit/e46a70e))
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
5
77
|
<a name="3.4.0"></a>
|
|
6
78
|
# [3.4.0](https://github.com/mongodb/node-mongodb-native/compare/v3.3.5...v3.4.0) (2019-12-10)
|
|
7
79
|
|
package/index.js
CHANGED
|
@@ -11,6 +11,7 @@ const connect = require('./lib/mongo_client').connect;
|
|
|
11
11
|
connect.MongoError = core.MongoError;
|
|
12
12
|
connect.MongoNetworkError = core.MongoNetworkError;
|
|
13
13
|
connect.MongoTimeoutError = core.MongoTimeoutError;
|
|
14
|
+
connect.MongoServerSelectionError = core.MongoServerSelectionError;
|
|
14
15
|
connect.MongoParseError = core.MongoParseError;
|
|
15
16
|
connect.MongoWriteConcernError = core.MongoWriteConcernError;
|
|
16
17
|
connect.MongoBulkWriteError = require('./lib/bulk/common').BulkWriteError;
|
package/lib/bulk/common.js
CHANGED
|
@@ -475,7 +475,7 @@ function mergeBatchResults(batch, bulkResult, err, result) {
|
|
|
475
475
|
if (Array.isArray(result.writeErrors)) {
|
|
476
476
|
for (let i = 0; i < result.writeErrors.length; i++) {
|
|
477
477
|
const writeError = {
|
|
478
|
-
index: batch.originalIndexes[i],
|
|
478
|
+
index: batch.originalIndexes[result.writeErrors[i].index],
|
|
479
479
|
code: result.writeErrors[i].code,
|
|
480
480
|
errmsg: result.writeErrors[i].errmsg,
|
|
481
481
|
op: batch.operations[result.writeErrors[i].index]
|
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const EventEmitter = require('events');
|
|
4
|
+
const MessageStream = require('./message_stream');
|
|
5
|
+
const MongoError = require('../core/error').MongoError;
|
|
6
|
+
const MongoNetworkError = require('../core/error').MongoNetworkError;
|
|
7
|
+
const MongoWriteConcernError = require('../core/error').MongoWriteConcernError;
|
|
8
|
+
const CommandResult = require('../core/connection/command_result');
|
|
9
|
+
const StreamDescription = require('./stream_description').StreamDescription;
|
|
10
|
+
const wp = require('../core/wireprotocol');
|
|
11
|
+
const apm = require('../core/connection/apm');
|
|
12
|
+
const updateSessionFromResponse = require('../core/sessions').updateSessionFromResponse;
|
|
13
|
+
const uuidV4 = require('../core/utils').uuidV4;
|
|
14
|
+
|
|
15
|
+
const kStream = Symbol('stream');
|
|
16
|
+
const kQueue = Symbol('queue');
|
|
17
|
+
const kMessageStream = Symbol('messageStream');
|
|
18
|
+
const kGeneration = Symbol('generation');
|
|
19
|
+
const kLastUseTime = Symbol('lastUseTime');
|
|
20
|
+
const kClusterTime = Symbol('clusterTime');
|
|
21
|
+
const kDescription = Symbol('description');
|
|
22
|
+
const kIsMaster = Symbol('ismaster');
|
|
23
|
+
const kAutoEncrypter = Symbol('autoEncrypter');
|
|
24
|
+
|
|
25
|
+
class Connection extends EventEmitter {
|
|
26
|
+
constructor(stream, options) {
|
|
27
|
+
super(options);
|
|
28
|
+
|
|
29
|
+
this.id = options.id;
|
|
30
|
+
this.address = streamIdentifier(stream);
|
|
31
|
+
this.bson = options.bson;
|
|
32
|
+
this.socketTimeout = typeof options.socketTimeout === 'number' ? options.socketTimeout : 360000;
|
|
33
|
+
this.monitorCommands =
|
|
34
|
+
typeof options.monitorCommands === 'boolean' ? options.monitorCommands : false;
|
|
35
|
+
this.closed = false;
|
|
36
|
+
this.destroyed = false;
|
|
37
|
+
|
|
38
|
+
this[kDescription] = new StreamDescription(this.address, options);
|
|
39
|
+
this[kGeneration] = options.generation;
|
|
40
|
+
this[kLastUseTime] = Date.now();
|
|
41
|
+
|
|
42
|
+
// retain a reference to an `AutoEncrypter` if present
|
|
43
|
+
if (options.autoEncrypter) {
|
|
44
|
+
this[kAutoEncrypter] = options.autoEncrypter;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// setup parser stream and message handling
|
|
48
|
+
this[kQueue] = new Map();
|
|
49
|
+
this[kMessageStream] = new MessageStream(options);
|
|
50
|
+
this[kMessageStream].on('message', messageHandler(this));
|
|
51
|
+
this[kStream] = stream;
|
|
52
|
+
stream.on('error', () => {
|
|
53
|
+
/* ignore errors, listen to `close` instead */
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
stream.on('close', () => {
|
|
57
|
+
if (this.closed) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
this.closed = true;
|
|
62
|
+
this[kQueue].forEach(op =>
|
|
63
|
+
op.cb(new MongoNetworkError(`connection ${this.id} to ${this.address} closed`))
|
|
64
|
+
);
|
|
65
|
+
this[kQueue].clear();
|
|
66
|
+
|
|
67
|
+
this.emit('close');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
stream.on('timeout', () => {
|
|
71
|
+
if (this.closed) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
stream.destroy();
|
|
76
|
+
this.closed = true;
|
|
77
|
+
this[kQueue].forEach(op =>
|
|
78
|
+
op.cb(new MongoNetworkError(`connection ${this.id} to ${this.address} timed out`))
|
|
79
|
+
);
|
|
80
|
+
this[kQueue].clear();
|
|
81
|
+
|
|
82
|
+
this.emit('close');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// hook the message stream up to the passed in stream
|
|
86
|
+
stream.pipe(this[kMessageStream]);
|
|
87
|
+
this[kMessageStream].pipe(stream);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
get description() {
|
|
91
|
+
return this[kDescription];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
get ismaster() {
|
|
95
|
+
return this[kIsMaster];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// the `connect` method stores the result of the handshake ismaster on the connection
|
|
99
|
+
set ismaster(response) {
|
|
100
|
+
this[kDescription].receiveResponse(response);
|
|
101
|
+
|
|
102
|
+
// TODO: remove this, and only use the `StreamDescription` in the future
|
|
103
|
+
this[kIsMaster] = response;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
get generation() {
|
|
107
|
+
return this[kGeneration] || 0;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
get idleTime() {
|
|
111
|
+
return Date.now() - this[kLastUseTime];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
get clusterTime() {
|
|
115
|
+
return this[kClusterTime];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
get stream() {
|
|
119
|
+
return this[kStream];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
markAvailable() {
|
|
123
|
+
this[kLastUseTime] = Date.now();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
destroy(options, callback) {
|
|
127
|
+
if (typeof options === 'function') {
|
|
128
|
+
callback = options;
|
|
129
|
+
options = {};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
options = Object.assign({ force: false }, options);
|
|
133
|
+
if (this[kStream] == null || this.destroyed) {
|
|
134
|
+
this.destroyed = true;
|
|
135
|
+
if (typeof callback === 'function') {
|
|
136
|
+
callback();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (options.force) {
|
|
143
|
+
this[kStream].destroy();
|
|
144
|
+
this.destroyed = true;
|
|
145
|
+
if (typeof callback === 'function') {
|
|
146
|
+
callback();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
this[kStream].end(err => {
|
|
153
|
+
this.destroyed = true;
|
|
154
|
+
if (typeof callback === 'function') {
|
|
155
|
+
callback(err);
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Wire protocol methods
|
|
161
|
+
command(ns, cmd, options, callback) {
|
|
162
|
+
wp.command(makeServerTrampoline(this), ns, cmd, options, callback);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
query(ns, cmd, cursorState, options, callback) {
|
|
166
|
+
wp.query(makeServerTrampoline(this), ns, cmd, cursorState, options, callback);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
getMore(ns, cursorState, batchSize, options, callback) {
|
|
170
|
+
wp.getMore(makeServerTrampoline(this), ns, cursorState, batchSize, options, callback);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
killCursors(ns, cursorState, callback) {
|
|
174
|
+
wp.killCursors(makeServerTrampoline(this), ns, cursorState, callback);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
insert(ns, ops, options, callback) {
|
|
178
|
+
wp.insert(makeServerTrampoline(this), ns, ops, options, callback);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
update(ns, ops, options, callback) {
|
|
182
|
+
wp.update(makeServerTrampoline(this), ns, ops, options, callback);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
remove(ns, ops, options, callback) {
|
|
186
|
+
wp.remove(makeServerTrampoline(this), ns, ops, options, callback);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/// This lets us emulate a legacy `Server` instance so we can work with the existing wire
|
|
191
|
+
/// protocol methods. Eventually, the operation executor will return a `Connection` to execute
|
|
192
|
+
/// against.
|
|
193
|
+
function makeServerTrampoline(connection) {
|
|
194
|
+
const server = {
|
|
195
|
+
description: connection.description,
|
|
196
|
+
clusterTime: connection[kClusterTime],
|
|
197
|
+
s: {
|
|
198
|
+
bson: connection.bson,
|
|
199
|
+
pool: { write: write.bind(connection), isConnected: () => true }
|
|
200
|
+
}
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
if (connection[kAutoEncrypter]) {
|
|
204
|
+
server.autoEncrypter = connection[kAutoEncrypter];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return server;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function messageHandler(conn) {
|
|
211
|
+
return function messageHandler(message) {
|
|
212
|
+
// always emit the message, in case we are streaming
|
|
213
|
+
conn.emit('message', message);
|
|
214
|
+
if (!conn[kQueue].has(message.responseTo)) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const operationDescription = conn[kQueue].get(message.responseTo);
|
|
219
|
+
conn[kQueue].delete(message.responseTo);
|
|
220
|
+
|
|
221
|
+
const callback = operationDescription.cb;
|
|
222
|
+
if (operationDescription.socketTimeoutOverride) {
|
|
223
|
+
conn[kStream].setTimeout(conn.socketTimeout);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
try {
|
|
227
|
+
// Pass in the entire description because it has BSON parsing options
|
|
228
|
+
message.parse(operationDescription);
|
|
229
|
+
} catch (err) {
|
|
230
|
+
callback(new MongoError(err));
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (message.documents[0]) {
|
|
235
|
+
const document = message.documents[0];
|
|
236
|
+
const session = operationDescription.session;
|
|
237
|
+
if (session) {
|
|
238
|
+
updateSessionFromResponse(session, document);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (document.$clusterTime) {
|
|
242
|
+
conn[kClusterTime] = document.$clusterTime;
|
|
243
|
+
conn.emit('clusterTimeReceived', document.$clusterTime);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (operationDescription.command) {
|
|
247
|
+
if (document.writeConcernError) {
|
|
248
|
+
callback(new MongoWriteConcernError(document.writeConcernError, document));
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (document.ok === 0 || document.$err || document.errmsg || document.code) {
|
|
253
|
+
callback(new MongoError(document));
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// NODE-2382: reenable in our glorious non-leaky abstraction future
|
|
260
|
+
// callback(null, operationDescription.fullResult ? message : message.documents[0]);
|
|
261
|
+
|
|
262
|
+
callback(
|
|
263
|
+
undefined,
|
|
264
|
+
new CommandResult(
|
|
265
|
+
operationDescription.fullResult ? message : message.documents[0],
|
|
266
|
+
conn,
|
|
267
|
+
message
|
|
268
|
+
)
|
|
269
|
+
);
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
function streamIdentifier(stream) {
|
|
274
|
+
if (typeof stream.address === 'function') {
|
|
275
|
+
return `${stream.remoteAddress}:${stream.remotePort}`;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return uuidV4().toString('hex');
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Not meant to be called directly, the wire protocol methods call this assuming it is a `Pool` instance
|
|
282
|
+
function write(command, options, callback) {
|
|
283
|
+
if (typeof options === 'function') {
|
|
284
|
+
callback = options;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
options = options || {};
|
|
288
|
+
const operationDescription = {
|
|
289
|
+
requestId: command.requestId,
|
|
290
|
+
cb: callback,
|
|
291
|
+
session: options.session,
|
|
292
|
+
fullResult: typeof options.fullResult === 'boolean' ? options.fullResult : false,
|
|
293
|
+
noResponse: typeof options.noResponse === 'boolean' ? options.noResponse : false,
|
|
294
|
+
documentsReturnedIn: options.documentsReturnedIn,
|
|
295
|
+
command: !!options.command,
|
|
296
|
+
|
|
297
|
+
// for BSON parsing
|
|
298
|
+
promoteLongs: typeof options.promoteLongs === 'boolean' ? options.promoteLongs : true,
|
|
299
|
+
promoteValues: typeof options.promoteValues === 'boolean' ? options.promoteValues : true,
|
|
300
|
+
promoteBuffers: typeof options.promoteBuffers === 'boolean' ? options.promoteBuffers : false,
|
|
301
|
+
raw: typeof options.raw === 'boolean' ? options.raw : false
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
if (this[kDescription] && this[kDescription].compressor) {
|
|
305
|
+
operationDescription.agreedCompressor = this[kDescription].compressor;
|
|
306
|
+
|
|
307
|
+
if (this[kDescription].zlibCompressionLevel) {
|
|
308
|
+
operationDescription.zlibCompressionLevel = this[kDescription].zlibCompressionLevel;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (typeof options.socketTimeout === 'number') {
|
|
313
|
+
operationDescription.socketTimeoutOverride = true;
|
|
314
|
+
this[kStream].setTimeout(options.socketTimeout);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// if command monitoring is enabled we need to modify the callback here
|
|
318
|
+
if (this.monitorCommands) {
|
|
319
|
+
this.emit('commandStarted', new apm.CommandStartedEvent(this, command));
|
|
320
|
+
|
|
321
|
+
operationDescription.started = process.hrtime();
|
|
322
|
+
operationDescription.cb = (err, reply) => {
|
|
323
|
+
if (err) {
|
|
324
|
+
this.emit(
|
|
325
|
+
'commandFailed',
|
|
326
|
+
new apm.CommandFailedEvent(this, command, err, operationDescription.started)
|
|
327
|
+
);
|
|
328
|
+
} else {
|
|
329
|
+
if (reply && reply.result && (reply.result.ok === 0 || reply.result.$err)) {
|
|
330
|
+
this.emit(
|
|
331
|
+
'commandFailed',
|
|
332
|
+
new apm.CommandFailedEvent(this, command, reply.result, operationDescription.started)
|
|
333
|
+
);
|
|
334
|
+
} else {
|
|
335
|
+
this.emit(
|
|
336
|
+
'commandSucceeded',
|
|
337
|
+
new apm.CommandSucceededEvent(this, command, reply, operationDescription.started)
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (typeof callback === 'function') {
|
|
343
|
+
callback(err, reply);
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
if (!operationDescription.noResponse) {
|
|
349
|
+
this[kQueue].set(operationDescription.requestId, operationDescription);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
try {
|
|
353
|
+
this[kMessageStream].writeCommand(command, operationDescription);
|
|
354
|
+
} catch (e) {
|
|
355
|
+
if (!operationDescription.noResponse) {
|
|
356
|
+
this[kQueue].delete(operationDescription.requestId);
|
|
357
|
+
operationDescription.cb(e);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (operationDescription.noResponse) {
|
|
363
|
+
operationDescription.cb();
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
module.exports = {
|
|
368
|
+
Connection
|
|
369
|
+
};
|