diff --git a/lib/core/connection/pool.js b/lib/core/connection/pool.js index 9a49ca02cd..adc8590038 100644 --- a/lib/core/connection/pool.js +++ b/lib/core/connection/pool.js @@ -3,7 +3,7 @@ const inherits = require('util').inherits; const EventEmitter = require('events').EventEmitter; const MongoError = require('../error').MongoError; -const MongoNetworkError = require('../error').MongoNetworkError; +const MongoTimeoutError = require('../error').MongoTimeoutError; const MongoWriteConcernError = require('../error').MongoWriteConcernError; const Logger = require('./logger'); const f = require('util').format; @@ -113,7 +113,9 @@ var Pool = function(topology, options) { reconnectInterval: 1000, reconnectTries: 30, // Enable domains - domainsEnabled: false + domainsEnabled: false, + // feature flag for determining if we are running with the unified topology or not + legacyCompatMode: true }, options ); @@ -123,6 +125,7 @@ var Pool = function(topology, options) { // Current reconnect retries this.retriesLeft = this.options.reconnectTries; this.reconnectId = null; + this.reconnectError = null; // No bson parser passed in if ( !options.bson || @@ -289,6 +292,7 @@ function connectionFailureHandler(pool, event, err, conn) { // Start reconnection attempts if (!pool.reconnectId && pool.options.reconnect) { + pool.reconnectError = err; pool.reconnectId = setTimeout(attemptReconnect(pool), pool.options.reconnectInterval); } @@ -315,10 +319,11 @@ function attemptReconnect(pool, callback) { if (pool.retriesLeft <= 0) { pool.destroy(); - const error = new MongoNetworkError( + const error = new MongoTimeoutError( `failed to reconnect after ${pool.options.reconnectTries} attempts with interval ${ pool.options.reconnectInterval - } ms` + } ms`, + pool.reconnectError ); pool.emit('reconnectFailed', error); @@ -333,7 +338,17 @@ function attemptReconnect(pool, callback) { pool.reconnectId = null; // now retry creating a connection - createConnection(pool, callback); + createConnection(pool, (err, conn) => { + if (err == null) { + pool.reconnectId = null; + pool.retriesLeft = pool.options.reconnectTries; + pool.emit('reconnect', pool); + } + + if (typeof callback === 'function') { + callback(err, conn); + } + }); }; } @@ -943,7 +958,23 @@ function createConnection(pool, callback) { pool.logger.debug(`connection attempt failed with error [${JSON.stringify(err)}]`); } + if (pool.options.legacyCompatMode === false) { + // The unified topology uses the reported `error` from a pool to track what error + // reason is returned to the user during selection timeout. We only want to emit + // this if the pool is active because the listeners are removed on destruction. + if (pool.state !== DESTROYED && pool.state !== DESTROYING) { + pool.emit('error', err); + } + } + + // check if reconnect is enabled, and attempt retry if so if (!pool.reconnectId && pool.options.reconnect) { + if (pool.state === CONNECTING && pool.options.legacyCompatMode) { + callback(err); + return; + } + + pool.reconnectError = err; pool.reconnectId = setTimeout( attemptReconnect(pool, callback), pool.options.reconnectInterval @@ -978,13 +1009,6 @@ function createConnection(pool, callback) { pool.availableConnections.push(connection); - // if there is a reconnect in progress, reset state and emit event - if (pool.reconnectId) { - pool.reconnectId = null; - pool.retriesLeft = pool.options.reconnectTries; - pool.emit('reconnect', pool); - } - // if a callback was provided, return the connection if (typeof callback === 'function') { callback(null, connection); diff --git a/lib/core/sdam/server.js b/lib/core/sdam/server.js index 6ba481f194..1c8d788a10 100644 --- a/lib/core/sdam/server.js +++ b/lib/core/sdam/server.js @@ -125,6 +125,7 @@ class Server extends EventEmitter { // NOTE: this should only be the case if we are connecting to a single server poolOptions.reconnect = true; + poolOptions.legacyCompatMode = false; this.s.pool = new Pool(this, poolOptions);