Skip to content

createConnection does not reconnect when initializing the connection while the DB is down #6244

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
tomgrossman opened this issue Mar 14, 2018 · 4 comments
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Milestone

Comments

@tomgrossman
Copy link

Do you want to request a feature or report a bug?
bug

What is the current behavior?
I'm initializing the DB connection with the createConnection function.
If I'm doing so while the DB is down, the readyState of the connection stays at 2 (connecting), and when starting the DB there is no re-connection until process restart.

If the current behavior is a bug, please provide the steps to reproduce.
using the following script:

const Promise       = require('bluebird');
const mongoose      = require('mongoose');
mongoose.Promise = Promise;

const DB_URL = 'mongodb://localhost:27017/test_database';

const DbConnection = mongoose.createConnection(DB_URL, {
    promiseLibrary: Promise,
    poolSize: 20,
    socketTimeoutMS: 0,
    connectTimeoutMS: 0,
    reconnectTries: Number.MAX_VALUE
});

let currentState = DbConnection.readyState;
let counter = 0 ;
console.log(DbConnection.readyState);
setInterval(() => {
    if (DbConnection.readyState === currentState) {
        counter++;
    } else {
        counter = 0;
        currentState = DbConnection.readyState;
    }
    console.log(DbConnection.readyState + ' - ' + counter);

}, 3000);

DbConnection.on('error', function (error) {
    console.log('error: ' + error.message)
});

DbConnection.on('disconnected', function () {
    console.log('disconnected');
});

DbConnection.on('close', function () {
    console.log('close');
});

DbConnection.on('open', function () {
    console.log('open');
});

DbConnection.on('connected', function () {
    console.log('connected');
});

DbConnection.on('connecting', function () {
    console.log('connecting');
});

DbConnection.on('reconnected', function () {
    console.log('reconnected');
});

process.on('unhandledRejection', function (err) {
    if ('MongoError' === err.name) {
        console.log('unhandledRejection: ' + err.message);
    }
});

module.exports = DbConnection;

while the DB is down from the beginning, the console output is:

2
error: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017]
2 - 1
2 - 2
2 - 3
2 - 4

and the counter continues to go up on the 2 readyState even when starting the DB in the middle.

What is the expected behavior?
The connection should re-connect after starting the DB. The re-connection works fine if the DB goes down and up in the middle of the running process.
For example, using the same script as above when the DB is up at the beginning, and goes down and up in the middle of the run, the console output is:

2
connected
open
1 - 0
1 - 1
disconnected
0 - 0
0 - 1
connected
reconnected
1 - 0
1 - 1

Please mention your node.js, mongoose and MongoDB version.
node.js - 8.10.0
mongoose - 5.0.10
MongoDB - 3.4

@ghost
Copy link

ghost commented Mar 14, 2018

Hi @tomgrossman

tl;dr reconnect only applies to previously established connections.

I was a little perplexed by this the first time I encountered it. This isn't a bug with mongoose but rather the intended behavior of the mongodb driver. There is at least one issue in mongodb's native driver bug tracker that proves we're not alone. Here is the link to the first one I found.

@tomgrossman
Copy link
Author

the readyState stays on 2 which is wrong, since it is not "connecting", so maybe it can be solved from mongoose side if the native driver ppl says it's as designed.

@ghost
Copy link

ghost commented Mar 15, 2018

the current callback to the driver's MongoClient.connect method only emits an error and rejects the promise without changing the readyState.

@vkarpov15 would it be a backwards breaking change to set the connection's readyState to disconnected in the initial error condition of the callback to .connect()?

something like:

        if (error) {
          if (_this.listeners('error').length > 0) {
            _this.emit('error', error);
          }
          _this.readyState = STATES.disconnected 
          return reject(error);
        }

example:

#!/usr/bin/env node
'use strict'
const noMongoOnPort = 'mongodb://localhost:27999/test'
const mongoose = require('mongoose')

const conn = mongoose.createConnection(noMongoOnPort, (e) => {
  console.log(`readyState: ${conn.readyState}\nerror.name ${e.name}`)
  process.exit(1)
})

output with .connect callback as it is now:

mongoose5: ./6244.js 
readyState: 2
error.name MongoNetworkError
mongoose5: 

output with proposed change

mongoose5: ./6244.js 
readyState: 0
error.name MongoNetworkError
mongoose5: 

@vkarpov15 vkarpov15 added this to the 5.0.12 milestone Mar 21, 2018
vkarpov15 added a commit that referenced this issue Mar 21, 2018
@vkarpov15 vkarpov15 added the confirmed-bug We've confirmed this is a bug in Mongoose and will fix it. label Mar 21, 2018
@vkarpov15
Copy link
Collaborator

@tomgrossman thanks for reporting, fixed in master and fix will be in 5.0.12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
confirmed-bug We've confirmed this is a bug in Mongoose and will fix it.
Projects
None yet
Development

No branches or pull requests

2 participants