Yesterday someone commented in my article on Sequel, where I compare it
with AR in some aspects, including pool management:
http://rosenfeld.herokuapp.com/en/articles/ruby-rails/2013-12-18-sequel-is-awesome-and-much-better-than-activerecord
To answer his comments I decided to first take a glance at the current
(4.1.1) implementation of how the connections' pool work in Rails with AR.
After our discussion in the comments, when I was about to sleep, I was
thinking more about this subject and decided it might worth bringing
some ideas to you, in case you'd be interested on them...
Basically, ActiveRecord currently relies on delegating the connection
pool management to the user. Most users don't realize it because they
don't usually spawn new threads from the main request thread and there's
an AR middleware that's automatically integrated to Rails that will
checkin the connection back to the pool in the end of the request. Since
the connection id is set in a thread local that means the Rack
middleware can only checkin the connection used in the main request
thread. Here's some example to illustrate:
class MainController
def index
Thread.start{Post.count }
head:ok
end
end
Assuming the default pool size (5), running this action 6 times will
fail currently:
ab -n 6 -c 1 http://localhost:3000/main/index
This is not anything new and Aaron Patterson has already touched this
subject long ago, in 2011:
http://tenderlovemaking.com/2011/10/20/connection-management-in-activerecord.html
In a side note, yesterday I learned about an interesting project to set
a common API for job libraries that is intended to be merged to Rails at
some point:
https://github.com/rails/activejob
The default adapter (inline) implements an "enqueue_at" method that will
spawn a new thread:
https://github.com/rails/activejob/blob/master/lib/active_job/queue_adapters/inline_adapter.rb#L9-L18
So, calling enqueue_at for a job using the default adapter will share
the same problems of the implementation above.
Then I was thinking that most of AR API could be implemented in a
smarter way, so that this wouldn't be a problem. That means calling
"with_connection" behind the scenes whenever they need a connection.
Also, even "execute" could be implemented this way. Instead of checking
out a connection by calling AR::Base.connection, it could simply return
a proxy. If you really want to checkout and reserve that connection you
could call "connection.lock" for instance and then the user would know
that they must ensure "unlock" is called after it's done. But otherwise,
calling "execute" would perform the query under a "with_connection"
block, checking the connection in back to the pool after running the SQL
statement.
I'm just suggesting the idea in case someone might be interested in
coming up with a PoC for this in case the core team agrees with the
suggested approach (it introduces a bit of backward incompatibilities).
I don't plan to work on this, specially because I don't use AR myself,
but maybe a better automatic handling of connections in the pool might
be of interest to most AR users...
Cheers,
Rodrigo.
--
You received this message because you are subscribed to the Google Groups "Ruby on
Rails: Core" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to rubyonrails-core+unsubscr...@googlegroups.com.
To post to this group, send email to rubyonrails-core@googlegroups.com.
Visit this group at http://groups.google.com/group/rubyonrails-core.
For more options, visit https://groups.google.com/d/optout.