grafthez
grafthez

Reputation: 4091

Is this preferred way to keep connection pool around in Ruby

I'm not very experienced in ruby (coding in java on daily basis) and I'm trying to find "the Ruby way" of keeping things like connection pools around. I've standalone Ruby app with multiple threads and I came up with something like below.

Note that MongoClient provided by native ruby driver for Mongo maintains conneciton pool internally, so all I need is to be able to keep one instance of MongoClient around

require 'mongo'

module MongoPool

  # module instance var to ensures only one exists
  @mongo = nil

  def self.lazy_create
    @mongo ||= Mongo::MongoClient.new('localhost', 27017, :pool_size => 5, :timeout => 5)
  end

  # when getting connection lazily create pool by assigning to @mongo only if nil
  def connection
    MongoPool.lazy_create
  end

end

class PeopleRepository

  include MongoPool

  def random_person
    coll = connection['test']['people']
    coll.find_one
  end

end

# usage
PeopleRepository.new.find_one

I know that works (checked that object_id of @mongo remains the same across several invocations), but is this preferred way to keep things around?

There may be more than one Repositories, so each can incluse MongoPool and use its connections. Are there any drawbacks of the solution above? Are there any other ways I should be aware of?

NOTE: The question is more about how to do things in Ruby way, not about how to do it in general (as I got it working).

Upvotes: 3

Views: 3701

Answers (2)

Brandon Black
Brandon Black

Reputation: 887

You don't really need another gem to do this and actually Mongoid's driver (Moped) doesn't support connection pooling yet anyway.

Similar to the recommendation to use an application level constant in rails, you just need to use a class variable in your headless application so that your MongoClient instance is the same single object/pool instance across all invocations of your application's base class.

For example, you could do something like this:

require 'mongo'

class MyApplication
  include Mongo

  # creates a single class instance, sets pool size but won't connect until used (lazy)
  @@client = MongoClient.new('localhost', 27017, :pool_size => 5, :connect => false)

  def do_something
    @@client['my_db']['my_collection].insert({ "foo" => "bar"})
  end
end

Simple and very straight-forward. The module approach you used above isn't necessary.

You mentioned Torquebox so I assume you're using JRuby and letting Torquebox manage your application's thread pool for you.

Make sure you're running version 1.8.3 or greater of the mongo ruby driver which includes some major fixes and improvements for running under that kind thread-heavy of setup. We addressed a few thread safety issues and greatly improved concurrency in the connection pool.

Hope that helps.

Upvotes: 5

phoet
phoet

Reputation: 18845

assuming you are using rails, i would do this:

# config/initializers/mongo.rb
MONGODB = Mongo::MongoClient.new('localhost', 27017, :pool_size => 5, :timeout => 5)

when you are using a library such as mongomapper, there are probably ways to configure pooling and just use it transparently.

have a look at mongo libraries here: http://railscasts.com/episodes/194-mongodb-and-mongomapper

Upvotes: 2

Related Questions