|# If your workers are inactive for a long period of time, they'll lose|
|# their MySQL connection.|
|# This hack ensures we re-connect whenever a connection is|
|# lost. Because, really. why not?|
|# Stick this in RAILS_ROOT/config/initializers/connection_fix.rb (or somewhere similar)|
|alias_method :execute_without_retry, :execute|
|rescue ActiveRecord::StatementInvalid => e|
|if e.message =~ /server has gone away/i|
|warn "Server timed out, retrying"|
Is there any reason to use this in applications using
I'm just wondering if these kinds of exceptions still crop up for people and reconnect code like this is necessary when the above technique is used to preemptively nuke stale connections from the connection pools?
I found that this fix caused me a whole lot of trouble with data integrity when I upgraded to Rails 3.1 from 2.3. I don't know what changed between the two versions, but basically, my
class User < ActiveRecord::Base has_many :posts end class Post < ActiveRecord::Base belongs_to :user end # ... User.transaction do u = User.create! sleep(10) p = Post.new p.user = u p.save! end
I found that a post row would be created with
We tried the connection fix on a site that is running on Rails2.3.14 with a lot of traffic and run into all kind of strange locking issues on the database. Once we removed the fix, it was all fine again. Can't really explain why this happend.
So.. I have been looking for alternative solutions. I have seen people who suggested to add ActiveRecord::Base.verify_active_connections! to your perform. I used an alternative approach by using the after_fork hook inside resque.rb in the config/initializers folder.
This seems to work fine. I wonder why other people are not suggesting this simple approach. Am I missing something?
I ended up doing the following.
module BaseJob def self.included(base) base.extend ClassMethods end module ClassMethods def perform(*args) ActiveRecord::Base.verify_active_connections! end end end
class FooJob include BaseJob @queue = :foo_queue def self.perform(arg) super foo_stuff end end
@mcjansen - Your after_fork solution might be a cleaner way to get this done.
Turns out there is already a plugin that is using the after_fork approach:
I had a bit trouble with the gist when migrating to mysql2 adapter. After checking the rails code I found out that the rails team implemented an AbstractMysqlAdapter so I changed the gist as follows. This should work with mysql and mysql2 adapter, right?
This should do the trick:
Resque.after_fork do clear_active_connections! end
This would work both before & after forking the child, since it wouldn't close active connections, but it would check everything back in to the connection pool, and checking back out from the pool verifies the connections.