Reputation: 40133
I am not clear on how to sequentially call Express middleware. I would like to have the next middleware in line only happen once the previous one is done. I thought that I had to call next() for it to happen but evidently that is not the case.
mongoose.connect(app.set("db-uri"));
app.use(function(req, res, next) {
if(1 !== mongoose.connection.readyState) {
console.log('Database not connected');
res.render("system/maintenance", {
status: 500
});
} else {
return next();
}
});
// This middleware does not wait for the previous next(). It just tries to connect before actually.
app.use(express.session({
secret: settings.sessionSecret,
maxAge: new Date(Date.now() + 3600000),
store: new MongoStore({ mongoose_connection: mongoose.connections[0], auto_reconnect: true })
}));
Edit: Updated code to only connect Mongoose on start and check state in middleware
Upvotes: 0
Views: 681
Reputation: 40133
Ok this seems to work. Open to comments on issues here.
var store;
mongoose.connect(app.set("db-uri"));
mongoose.connection.on("connect", function(err) {
// Create session store connection
store = new MongoStore({ mongoose_connection: mongoose.connections[0], auto_reconnect: true });
});
app.use(function(req, res, next) {
if(1 !== mongoose.connection.readyState) {
console.log('Database not connected');
// Try a restart else it will stay down even when db comes back up
mongoose.connect(app.set("db-uri"));
res.render("system/maintenance", {
status: 500
});
} else {
return next();
}
});
app.use(express.session({
secret: settings.sessionSecret,
maxAge: new Date(Date.now() + 3600000),
store: store
}));
Appears to work - I was concerned session store would not come back up but I think it works.
Upvotes: 0
Reputation: 14953
I admit this isn't a very complete answer, not to mention tested, but the gist of it should work.
First of all, connect to the database when starting the app, eg not in a middleware. Just put the moongoose.connect
stuff outside of app.use
somewhere (see any mongoose+express example, like this one).
Second, I'd use a "flag" that keeps track of whether or not mongoose has disconnected.
var mongooseIsConnected = false;
mongoose.on('open', function () {
mongooseIsConnected = true;
});
mongoose.on('error', function () {
mongooseIsConnected = false;
});
Note that this is very much a guess. I don't know if the error event fires only on connection failure and likewise I don't know if "open" fires when reconnecting. If you find that in some docs please tell me and I'll update this answer.
Finally it's straight forward to put a middleware – before any other middlewares using the database – which checks if the flag is true or false and either passes the request on or renders an error.
app.use(function (req, res, next) {
if(mongooseIsConnected) {
next();
}
else {
res.status(500);
res.render('errorView');
// Or you could call next(new Error('The database is broken')); and handle
// the error in a central express errorHandler
}
});
// app.use(express.session etc here...
mongoose.connect('uri...', configureApp);
function configureApp () {
app.use(express.session({
secret: settings.sessionSecret,
maxAge: new Date(Date.now() + 3600000),
store: new MongoStore({ mongoose_connection: mongoose.connections[0], auto_reconnect: true })
}));
// The other middleware and app.listen etc
}
This should ensure the connection is made before the middlewares are defined. However when digging though my own code I see that I simply let MongoStore create a new connection. That's probably easier.
Upvotes: 1