Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ActiveRecord::Base.connection.query_cache_enabled in sidekiq

I have a piece of code that performs the same queries over and over, and it's doing that in a background worker within a thread.

I checkout out the activerecord query cache middleware but apparently it needs to be enabled before use. However I'm not sure if it's a safe thing to do and if it will affect other running threads.

you can see the tests here: https://github.com/rails/rails/blob/3e36db4406beea32772b1db1e9a16cc1e8aea14c/activerecord/test/cases/query_cache_test.rb#L19

my question is: can I borrow and/or use the middleware directly to enable query cache for the duration of a block safely in a thread?

when I tried ActiveRecord::Base.cache do my CI started failing left and right...

like image 368
John Smith Avatar asked Jul 28 '15 13:07

John Smith


1 Answers

EDIT: Rails 5 and later: the ActiveRecord query cache is automatically enabled even for background jobs like Sidekiq (see: https://github.com/mperham/sidekiq/wiki/Problems-and-Troubleshooting#activerecord-query-cache for information on how to disable it).

Rails 4.x and earlier: The difficulty with applying ActiveRecord::QueryCache to your Sidekiq workers is that, aside from the implementation details of it being a middleware, it's meant to be built during the request and destroyed at the end of it. Since background jobs don't have a request, you need to be careful about when you clear the cache. A reasonable approach would be to cache only during the perform method, though.

So, to implement that, you'll probably need to write your own piece of Sidekiq middleware, based on ActiveRecord::QueryCache but following Sidekiq's middleware guide. E.g.,

class SidekiqQueryCacheMiddleware
  def call(worker, job, queue)
    connection    = ActiveRecord::Base.connection
    enabled       = connection.query_cache_enabled
    connection_id = ActiveRecord::Base.connection_id
    connection.enable_query_cache!

    yield
  ensure
    ActiveRecord::Base.connection_id = connection_id
    ActiveRecord::Base.connection.clear_query_cache
    ActiveRecord::Base.connection.disable_query_cache! unless enabled
  end
end
like image 200
Robert Nubel Avatar answered Oct 24 '22 04:10

Robert Nubel