meteor / meteor-feature-requests

A tracker for Meteor issues that are requests for new functionality, not bugs.
Other
89 stars 3 forks source link

Poll until Mongo is ready before starting Meteor #297

Open GeoffreyBooth opened 6 years ago

GeoffreyBooth commented 6 years ago

I sometimes run Meteor apps in a Docker environment, where docker-compose manages a MongoDB instance running as a separate Docker container. Since both the Meteor app container and the Mongo container start up at the same time, occasionally the Meteor container is ready first and immediately dies because it cannot connect to Mongo. The popular meteor-launchpad Docker project has a STARTUP_DELAY option where one can specify some number of seconds to wait before starting the Meteor app container, to allow the Mongo container some time to get ready before Meteor tries to connect to it.

It would be more robust to poll until MongoDB is ready before trying to use it. In my Docker entrypoint shell script for my Meteor app container, I have this code:

echo 'Connecting to MongoDB...'
node <<- 'EOJS'
require('p-wait-for')(function() {
  return new Promise(function (resolve) {
    require('mongodb').MongoClient.connect(process.env.MONGO_URL, function(err, client) {
      const successfullyConnected = err == null;
      if (successfullyConnected) {
        client.close();
      }
      resolve(successfullyConnected);
    });
  });
}, 1000);
EOJS

And a package.json that installs the p-wait-for and mongodb packages into the folder where this is run, outside of my Meteor app. This code uses the mongodb package to try to connect (and login) to a running MongoDB server, and retries every second until it succeeds. This is more robust than simply checking that the MongoDB port is open, and way more robust than simply waiting an arbitrary number of seconds.

I feel like this should be part of Meteor proper, though probably with a timeout so that it doesn’t poll indefinitely. What do you think? Where would the appropriate place be to put logic like this?

mitar commented 6 years ago

I use this script to wait in my Docker image.

mitar commented 6 years ago

But I agree. The same as how Meteor should reconnect during run, why not also try to reconnect at startup?

But Meteor.startup should run only after initial connection is established.

GeoffreyBooth commented 6 years ago

@mitar Do you care to add some comments to that script? In particular, I’m looking at the integers and wondering which ones are wait times, timeouts, or number of retry attempts. That script would probably be a better starting point than mine for something to be added to core.

mitar commented 6 years ago

I am not sure if it is really suitable. For core this should probably somewhere deep inside Meteor.

dr-dimitru commented 6 years ago

@GeoffreyBooth have you tried to set longer timeouts in connection string via connectTimeoutMS and socketTimeoutMS? Like:

mongodb://127.0.0.1:27017/myApp?connectTimeoutMS=999999&socketTimeoutMS=999999;
GeoffreyBooth commented 6 years ago

@dr-dimitru I haven’t, but I wouldn’t want to affect Meteor’s normal runtime behavior. I only want it to wait a long time for Mongo on startup, not thereafter.

dr-dimitru commented 6 years ago

@GeoffreyBooth I got your point. But just trying it may give us a good point to work with later.

KoenLav commented 5 years ago

@benjamn I believe this has been resolved in Meteor 1.8.1?