Erik B
Erik B

Reputation: 42614

MongoClient failed to connect to server on first connect, but connects later

I am very confused about how MongoClient.connect is supposed to be used. I have an express app that uses MongoDB and I'm working on deploying it with docker. When using docker-compose up, the app might try to connect to mongo before mongo is ready to accept connections. When this happens, I get the following error:

MongoNetworkError: failed to connect to server [mongo:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 172.18.0.2:27017]

That's fine, but it actually connects as soon the database is available. That would also be fine, but the promise is already rejected and I don't have anyway of using that connection. I also tried switching to using callbacks, but the callback is never called again after the failure.

I can always retry until I get a working connection without an error, but for every time I retry, I get another connection to the database that isn't closed until the application restarts, which normally is when a new version is deployed.

I either need a way to use the connection that initially failed or stop the failed connections from retrying. Does anyone have a clue how to accomplish this?

Upvotes: 2

Views: 745

Answers (2)

kevinadi
kevinadi

Reputation: 13805

If you're starting your containers all at once, the MongoDB container might not be up before your app container.

You can Control startup order in Compose to ensure that the MongoDB container is up before the app container, e.g. by using the depends_on directive. From an example on the linked page:

version: "2"
services:
  web:
    build: .
    ports:
      - "80:8000"
    depends_on:
      - "db"
    command: ["./wait-for-it.sh", "db:5432", "--", "python", "app.py"]
  db:
    image: mongodb

However note that as mentioned in the depends_on documentation, it is not a complete solution since it only waits until the container is started, not necessarily until the database is started.

You would need to use depends_on in combination with a script like wait-for-it to ensure the database is actually up.

Upvotes: 1

JohnnyHK
JohnnyHK

Reputation: 312129

The 3.0 version of the Node.js MongoDB driver gives you some additional flexibility here as you can create your own MongoClient object and use its methods to connect, check if you're still connected, and disconnect as needed:

let mc = new mongodb.MongoClient('mongodb://localhost');

await mc.connect();

if (mc.isConnected()) { ... }

let db = mc.db('test');
let collection = db.collection("test");

...

await mc.close();

Upvotes: 1

Related Questions