I am trying to write an expressjs server utilizing the postgresql as the backend. Each request starts by calling pg.connect
to get a pooled connection (client
) as well as the method to return it to the pool once the connection is no longer needed (done
). For example:
function dbConnect(req, res, next) {
if (res.locals.pgCtx) {
next();
return;
}
pg.connect(dbConn, function (err, client, done) {
if (err) {
res.send(500, err.message);
} else {
app.locals.pgCtx = res.locals.pgCtx = {
client: client,
done: done
};
next();
}
});
}
app.use(allowCrossDomain);
app.use(express.methodOverride());
app.use(express.compress());
app.use(express.bodyParser());
app.use(express.logger());
app.use(passport.initialize());
app.use(express["static"](webRootDir));
app.use(dbConnect); // <--------------
app.use(authenticate);
app.use(app.router);
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
app.set('view engine', 'jade');
app.set('views', webRootDir);
app.engine("jade", jade.__express);
indexHandlers = [fetchConstData, function (req, res) {
res.render(templatesDir + 'index', {
constData: app.locals.constData,
env: app.get('env'),
user: req.user,
admin: isAdmin(req.user.role),
host: req.host
});
}];
app.get('/', indexHandlers);
app.get('/index', indexHandlers);
app.get('/index.html', indexHandlers);
My problem is that while I can insert dbConnect
as the global middleware to be run before any other middleware for a request I also need to be able to cleanup after all the middleware is run in order to return the connection back to the pool.
Ideally, there should be a way to specify a global middleware to be run after all the request specific ones are run regardless of how the request ends - be it by:
res.send(...)
next()
Note, that any request specific middleware can terminate the chain in this way.
Right now I can see only this approach:
express.errorHandler
.res.send
method in the res
object by a custom version that returns the connection back to pool first and then proceeds to the original res.send
implementation.All of this has a strong smell of a hack. I would like to do it right and so I am asking is there a way to register something like a request cleanup middleware?
EDIT
The static content handler must be moved above the dbConnect
middleware, otherwise we leak db connections until no more connections are available and the server is unable to serve anything because dbConnect
never returns waiting for a connection to be released.
There's a finish
event that you can listen for on the response object and which will be emitted when the response has finished:
function dbConnect(req, res, next) {
res.on('finish', function() {
// perform your cleanups...
});
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With