mongodb 2.2.36 → 3.0.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.
@@ -0,0 +1,444 @@
1
+ 'use strict';
2
+
3
+ var ServerCapabilities = require('./topology_base').ServerCapabilities,
4
+ TopologyBase = require('./topology_base').TopologyBase,
5
+ MongoError = require('mongodb-core').MongoError,
6
+ CMongos = require('mongodb-core').Mongos,
7
+ Cursor = require('../cursor'),
8
+ AggregationCursor = require('../aggregation_cursor'),
9
+ CommandCursor = require('../command_cursor'),
10
+ Define = require('../metadata'),
11
+ Server = require('./server'),
12
+ Store = require('./topology_base').Store,
13
+ MAX_JS_INT = require('../utils').MAX_JS_INT,
14
+ translateOptions = require('../utils').translateOptions,
15
+ filterOptions = require('../utils').filterOptions,
16
+ mergeOptions = require('../utils').mergeOptions;
17
+
18
+ /**
19
+ * @fileOverview The **Mongos** class is a class that represents a Mongos Proxy topology and is
20
+ * used to construct connections.
21
+ *
22
+ * **Mongos Should not be used, use MongoClient.connect**
23
+ */
24
+
25
+ // Allowed parameters
26
+ var legalOptionNames = [
27
+ 'ha',
28
+ 'haInterval',
29
+ 'acceptableLatencyMS',
30
+ 'poolSize',
31
+ 'ssl',
32
+ 'checkServerIdentity',
33
+ 'sslValidate',
34
+ 'sslCA',
35
+ 'sslCRL',
36
+ 'sslCert',
37
+ 'ciphers',
38
+ 'ecdhCurve',
39
+ 'sslKey',
40
+ 'sslPass',
41
+ 'socketOptions',
42
+ 'bufferMaxEntries',
43
+ 'store',
44
+ 'auto_reconnect',
45
+ 'autoReconnect',
46
+ 'emitError',
47
+ 'keepAlive',
48
+ 'keepAliveInitialDelay',
49
+ 'noDelay',
50
+ 'connectTimeoutMS',
51
+ 'socketTimeoutMS',
52
+ 'loggerLevel',
53
+ 'logger',
54
+ 'reconnectTries',
55
+ 'appname',
56
+ 'domainsEnabled',
57
+ 'servername',
58
+ 'promoteLongs',
59
+ 'promoteValues',
60
+ 'promoteBuffers',
61
+ 'promiseLibrary'
62
+ ];
63
+
64
+ /**
65
+ * Creates a new Mongos instance
66
+ * @class
67
+ * @deprecated
68
+ * @param {Server[]} servers A seedlist of servers participating in the replicaset.
69
+ * @param {object} [options=null] Optional settings.
70
+ * @param {booelan} [options.ha=true] Turn on high availability monitoring.
71
+ * @param {number} [options.haInterval=5000] Time between each replicaset status check.
72
+ * @param {number} [options.poolSize=5] Number of connections in the connection pool for each server instance, set to 5 as default for legacy reasons.
73
+ * @param {number} [options.acceptableLatencyMS=15] Cutoff latency point in MS for MongoS proxy selection
74
+ * @param {boolean} [options.ssl=false] Use ssl connection (needs to have a mongod server with ssl support)
75
+ * @param {boolean|function} [options.checkServerIdentity=true] Ensure we check server identify during SSL, set to false to disable checking. Only works for Node 0.12.x or higher. You can pass in a boolean or your own checkServerIdentity override function.
76
+ * @param {object} [options.sslValidate=true] Validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher)
77
+ * @param {array} [options.sslCA=null] Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
78
+ * @param {array} [options.sslCRL=null] Array of revocation certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
79
+ * @param {string} [options.ciphers=null] Passed directly through to tls.createSecureContext. See https://nodejs.org/dist/latest-v9.x/docs/api/tls.html#tls_tls_createsecurecontext_options for more info.
80
+ * @param {string} [options.ecdhCurve=null] Passed directly through to tls.createSecureContext. See https://nodejs.org/dist/latest-v9.x/docs/api/tls.html#tls_tls_createsecurecontext_options for more info.
81
+ * @param {(Buffer|string)} [options.sslCert=null] String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
82
+ * @param {(Buffer|string)} [options.sslKey=null] String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
83
+ * @param {(Buffer|string)} [options.sslPass=null] String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher)
84
+ * @param {string} [options.servername=null] String containing the server name requested via TLS SNI.
85
+ * @param {object} [options.socketOptions=null] Socket options
86
+ * @param {boolean} [options.socketOptions.noDelay=true] TCP Socket NoDelay option.
87
+ * @param {boolean} [options.socketOptions.keepAlive=true] TCP Connection keep alive enabled
88
+ * @param {number} [options.socketOptions.keepAliveInitialDelay=30000] The number of milliseconds to wait before initiating keepAlive on the TCP socket
89
+ * @param {number} [options.socketOptions.connectTimeoutMS=0] TCP Connection timeout setting
90
+ * @param {number} [options.socketOptions.socketTimeoutMS=0] TCP Socket timeout setting
91
+ * @param {boolean} [options.domainsEnabled=false] Enable the wrapping of the callback in the current domain, disabled by default to avoid perf hit.
92
+ * @fires Mongos#connect
93
+ * @fires Mongos#ha
94
+ * @fires Mongos#joined
95
+ * @fires Mongos#left
96
+ * @fires Mongos#fullsetup
97
+ * @fires Mongos#open
98
+ * @fires Mongos#close
99
+ * @fires Mongos#error
100
+ * @fires Mongos#timeout
101
+ * @fires Mongos#parseError
102
+ * @property {string} parserType the parser type used (c++ or js).
103
+ * @return {Mongos} a Mongos instance.
104
+ */
105
+ class Mongos extends TopologyBase {
106
+ constructor(servers, options) {
107
+ super();
108
+
109
+ options = options || {};
110
+ var self = this;
111
+
112
+ // Filter the options
113
+ options = filterOptions(options, legalOptionNames);
114
+
115
+ // Ensure all the instances are Server
116
+ for (var i = 0; i < servers.length; i++) {
117
+ if (!(servers[i] instanceof Server)) {
118
+ throw MongoError.create({
119
+ message: 'all seed list instances must be of the Server type',
120
+ driver: true
121
+ });
122
+ }
123
+ }
124
+
125
+ // Stored options
126
+ var storeOptions = {
127
+ force: false,
128
+ bufferMaxEntries:
129
+ typeof options.bufferMaxEntries === 'number' ? options.bufferMaxEntries : MAX_JS_INT
130
+ };
131
+
132
+ // Shared global store
133
+ var store = options.store || new Store(self, storeOptions);
134
+
135
+ // Build seed list
136
+ var seedlist = servers.map(function(x) {
137
+ return { host: x.host, port: x.port };
138
+ });
139
+
140
+ // Get the reconnect option
141
+ var reconnect = typeof options.auto_reconnect === 'boolean' ? options.auto_reconnect : true;
142
+ reconnect = typeof options.autoReconnect === 'boolean' ? options.autoReconnect : reconnect;
143
+
144
+ // Clone options
145
+ var clonedOptions = mergeOptions(
146
+ {},
147
+ {
148
+ disconnectHandler: store,
149
+ cursorFactory: Cursor,
150
+ reconnect: reconnect,
151
+ emitError: typeof options.emitError === 'boolean' ? options.emitError : true,
152
+ size: typeof options.poolSize === 'number' ? options.poolSize : 5
153
+ }
154
+ );
155
+
156
+ // Translate any SSL options and other connectivity options
157
+ clonedOptions = translateOptions(clonedOptions, options);
158
+
159
+ // Socket options
160
+ var socketOptions =
161
+ options.socketOptions && Object.keys(options.socketOptions).length > 0
162
+ ? options.socketOptions
163
+ : options;
164
+
165
+ // Translate all the options to the mongodb-core ones
166
+ clonedOptions = translateOptions(clonedOptions, socketOptions);
167
+
168
+ // Build default client information
169
+ clonedOptions.clientInfo = this.clientInfo;
170
+ // Do we have an application specific string
171
+ if (options.appname) {
172
+ clonedOptions.clientInfo.application = { name: options.appname };
173
+ }
174
+
175
+ // Internal state
176
+ this.s = {
177
+ // Create the Mongos
178
+ coreTopology: new CMongos(seedlist, clonedOptions),
179
+ // Server capabilities
180
+ sCapabilities: null,
181
+ // Debug turned on
182
+ debug: clonedOptions.debug,
183
+ // Store option defaults
184
+ storeOptions: storeOptions,
185
+ // Cloned options
186
+ clonedOptions: clonedOptions,
187
+ // Actual store of callbacks
188
+ store: store,
189
+ // Options
190
+ options: options,
191
+ // Server Session Pool
192
+ sessionPool: null,
193
+ // Promise library
194
+ promiseLibrary: options.promiseLibrary || Promise
195
+ };
196
+ }
197
+
198
+ // Connect
199
+ connect(_options, callback) {
200
+ var self = this;
201
+ if ('function' === typeof _options) (callback = _options), (_options = {});
202
+ if (_options == null) _options = {};
203
+ if (!('function' === typeof callback)) callback = null;
204
+ _options = Object.assign({}, this.s.clonedOptions, _options);
205
+ self.s.options = _options;
206
+
207
+ // Update bufferMaxEntries
208
+ self.s.storeOptions.bufferMaxEntries =
209
+ typeof _options.bufferMaxEntries === 'number' ? _options.bufferMaxEntries : -1;
210
+
211
+ // Error handler
212
+ var connectErrorHandler = function() {
213
+ return function(err) {
214
+ // Remove all event handlers
215
+ var events = ['timeout', 'error', 'close'];
216
+ events.forEach(function(e) {
217
+ self.removeListener(e, connectErrorHandler);
218
+ });
219
+
220
+ self.s.coreTopology.removeListener('connect', connectErrorHandler);
221
+ // Force close the topology
222
+ self.close(true);
223
+
224
+ // Try to callback
225
+ try {
226
+ callback(err);
227
+ } catch (err) {
228
+ process.nextTick(function() {
229
+ throw err;
230
+ });
231
+ }
232
+ };
233
+ };
234
+
235
+ // Actual handler
236
+ var errorHandler = function(event) {
237
+ return function(err) {
238
+ if (event !== 'error') {
239
+ self.emit(event, err);
240
+ }
241
+ };
242
+ };
243
+
244
+ // Error handler
245
+ var reconnectHandler = function() {
246
+ self.emit('reconnect');
247
+ self.s.store.execute();
248
+ };
249
+
250
+ // relay the event
251
+ var relay = function(event) {
252
+ return function(t, server) {
253
+ self.emit(event, t, server);
254
+ };
255
+ };
256
+
257
+ // Connect handler
258
+ var connectHandler = function() {
259
+ // Clear out all the current handlers left over
260
+ var events = ['timeout', 'error', 'close', 'fullsetup'];
261
+ events.forEach(function(e) {
262
+ self.s.coreTopology.removeAllListeners(e);
263
+ });
264
+
265
+ // Set up listeners
266
+ self.s.coreTopology.once('timeout', errorHandler('timeout'));
267
+ self.s.coreTopology.once('error', errorHandler('error'));
268
+ self.s.coreTopology.once('close', errorHandler('close'));
269
+
270
+ // Set up serverConfig listeners
271
+ self.s.coreTopology.on('fullsetup', function() {
272
+ self.emit('fullsetup', self);
273
+ });
274
+
275
+ // Emit open event
276
+ self.emit('open', null, self);
277
+
278
+ // Return correctly
279
+ try {
280
+ callback(null, self);
281
+ } catch (err) {
282
+ process.nextTick(function() {
283
+ throw err;
284
+ });
285
+ }
286
+ };
287
+
288
+ // Clear out all the current handlers left over
289
+ var events = [
290
+ 'timeout',
291
+ 'error',
292
+ 'close',
293
+ 'serverOpening',
294
+ 'serverDescriptionChanged',
295
+ 'serverHeartbeatStarted',
296
+ 'serverHeartbeatSucceeded',
297
+ 'serverHeartbeatFailed',
298
+ 'serverClosed',
299
+ 'topologyOpening',
300
+ 'topologyClosed',
301
+ 'topologyDescriptionChanged'
302
+ ];
303
+ events.forEach(function(e) {
304
+ self.s.coreTopology.removeAllListeners(e);
305
+ });
306
+
307
+ // Set up SDAM listeners
308
+ self.s.coreTopology.on('serverDescriptionChanged', relay('serverDescriptionChanged'));
309
+ self.s.coreTopology.on('serverHeartbeatStarted', relay('serverHeartbeatStarted'));
310
+ self.s.coreTopology.on('serverHeartbeatSucceeded', relay('serverHeartbeatSucceeded'));
311
+ self.s.coreTopology.on('serverHeartbeatFailed', relay('serverHeartbeatFailed'));
312
+ self.s.coreTopology.on('serverOpening', relay('serverOpening'));
313
+ self.s.coreTopology.on('serverClosed', relay('serverClosed'));
314
+ self.s.coreTopology.on('topologyOpening', relay('topologyOpening'));
315
+ self.s.coreTopology.on('topologyClosed', relay('topologyClosed'));
316
+ self.s.coreTopology.on('topologyDescriptionChanged', relay('topologyDescriptionChanged'));
317
+
318
+ // Set up listeners
319
+ self.s.coreTopology.once('timeout', connectErrorHandler('timeout'));
320
+ self.s.coreTopology.once('error', connectErrorHandler('error'));
321
+ self.s.coreTopology.once('close', connectErrorHandler('close'));
322
+ self.s.coreTopology.once('connect', connectHandler);
323
+ // Join and leave events
324
+ self.s.coreTopology.on('joined', relay('joined'));
325
+ self.s.coreTopology.on('left', relay('left'));
326
+
327
+ // Reconnect server
328
+ self.s.coreTopology.on('reconnect', reconnectHandler);
329
+
330
+ // Start connection
331
+ self.s.coreTopology.connect(_options);
332
+ }
333
+ }
334
+
335
+ Object.defineProperty(Mongos.prototype, 'haInterval', {
336
+ enumerable: true,
337
+ get: function() {
338
+ return this.s.coreTopology.s.haInterval;
339
+ }
340
+ });
341
+
342
+ const define = (Mongos.define = new Define('Mongos', Mongos, false));
343
+ define.classMethod('capabilities', {
344
+ callback: false,
345
+ promise: false,
346
+ returns: [ServerCapabilities]
347
+ });
348
+
349
+ define.classMethod('command', { callback: true, promise: false });
350
+ define.classMethod('insert', { callback: true, promise: false });
351
+ define.classMethod('update', { callback: true, promise: false });
352
+ define.classMethod('remove', { callback: true, promise: false });
353
+ define.classMethod('isConnected', { callback: false, promise: false, returns: [Boolean] });
354
+ define.classMethod('isDestroyed', { callback: false, promise: false, returns: [Boolean] });
355
+ define.classMethod('cursor', {
356
+ callback: false,
357
+ promise: false,
358
+ returns: [Cursor, AggregationCursor, CommandCursor]
359
+ });
360
+
361
+ define.classMethod('close', { callback: false, promise: false });
362
+ define.classMethod('auth', { callback: true, promise: false });
363
+ define.classMethod('logout', { callback: true, promise: false });
364
+ define.classMethod('connections', { callback: false, promise: false, returns: [Array] });
365
+
366
+ /**
367
+ * A mongos connect event, used to verify that the connection is up and running
368
+ *
369
+ * @event Mongos#connect
370
+ * @type {Mongos}
371
+ */
372
+
373
+ /**
374
+ * The mongos high availability event
375
+ *
376
+ * @event Mongos#ha
377
+ * @type {function}
378
+ * @param {string} type The stage in the high availability event (start|end)
379
+ * @param {boolean} data.norepeat This is a repeating high availability process or a single execution only
380
+ * @param {number} data.id The id for this high availability request
381
+ * @param {object} data.state An object containing the information about the current replicaset
382
+ */
383
+
384
+ /**
385
+ * A server member left the mongos set
386
+ *
387
+ * @event Mongos#left
388
+ * @type {function}
389
+ * @param {string} type The type of member that left (primary|secondary|arbiter)
390
+ * @param {Server} server The server object that left
391
+ */
392
+
393
+ /**
394
+ * A server member joined the mongos set
395
+ *
396
+ * @event Mongos#joined
397
+ * @type {function}
398
+ * @param {string} type The type of member that joined (primary|secondary|arbiter)
399
+ * @param {Server} server The server object that joined
400
+ */
401
+
402
+ /**
403
+ * Mongos fullsetup event, emitted when all proxies in the topology have been connected to.
404
+ *
405
+ * @event Mongos#fullsetup
406
+ * @type {Mongos}
407
+ */
408
+
409
+ /**
410
+ * Mongos open event, emitted when mongos can start processing commands.
411
+ *
412
+ * @event Mongos#open
413
+ * @type {Mongos}
414
+ */
415
+
416
+ /**
417
+ * Mongos close event
418
+ *
419
+ * @event Mongos#close
420
+ * @type {object}
421
+ */
422
+
423
+ /**
424
+ * Mongos error event, emitted if there is an error listener.
425
+ *
426
+ * @event Mongos#error
427
+ * @type {MongoError}
428
+ */
429
+
430
+ /**
431
+ * Mongos timeout event
432
+ *
433
+ * @event Mongos#timeout
434
+ * @type {object}
435
+ */
436
+
437
+ /**
438
+ * Mongos parseError event
439
+ *
440
+ * @event Mongos#parseError
441
+ * @type {object}
442
+ */
443
+
444
+ module.exports = Mongos;