Reputation: 4091
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
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
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