RethinkDB – Too many open files

After dealing with RethinkDB “too many open files” errors for the past few weeks I finally submitted a github issue and discovered what the problem was – I wasn’t closing my connections.

I thought there was some kind of connection pooling in rethinkdb so when you did r.connection it would either use an existing connection or get a new one. Unfortunately this wasn’t the case. Turns out when you’re done with your connection you have to close it or it will tie up resources until the connection times out. Do it enough times and you’ll run into this too many open files error.

Here’s an example of how to code your nodejs models using rethinkdb best practices. This is based off the example on the rethinkdb site.

### rethinkdb-client.coffee ###

r = require('rethinkdb')
netconfig = require('../config/netconfig')

db = r
db.onConnect = (callback) ->
r.connect {host: netconfig.db.host, port: netconfig.db.port, db: 'towerstorm'}, (err, conn) ->
if err then throw new Error(err)
if !conn then throw new Error("No RethinkDB connection returned")
callback(err, conn)

module.exports = db
### user.coffee ###

db = require("./rethinkdb-client")

class User
data: null

constructor: (data) ->
@data = data

User.findById = (id, callback) ->
if !id then return callback(new Error("Invalid ID passed to User.findById"))
db.onConnect (err, conn) ->
if err then return callback(err)
db.table('users').get(id).run conn, (err, userInfo) ->
conn.close() #This is what I forgot, remember to do this
if err then return callback(err)
return callback(null, new User(userInfo))

User.findByUsername = (username, callback) ->
db.onConnect (err, conn) =>
if err then return callback(err)
db.table('users').getAll(username, {index: 'username'}).run conn, (err, cursor) ->
if err then return callback(err)
cursor.toArray (err, results) ->
conn.close() #Do this after cursor.toArray, not before
users = results.map((userInfo) -> new User(userInfo))
return callback(null, users)


If you’re only getting one item you should close the connection immediately after the run() callback returns. If you’re getting multiple items you’ll get a cursor instead of a single item to your callback so call conn.close() after you’ve done cursor.toArray().

 

tim