Search code examples
ruby-on-railspostgresqlactiverecordpuma

Rails, Puma, Postgres: Preloading Active Record definitions?


After every boot, I see queries like these to the database:

enter image description here

Once each puma worker is hit once with a request (that hits the database), these go away. It's annoying because it can add 50+ sql queries to a request (1s +). What I want to do is somehow preload these every time a worker boots.

I've tried

on_worker_boot do
  ActiveSupport.on_load(:active_record) do
    ActiveRecord::Base.establish_connection
  end
  Rails.application.eager_load!
  ::Rails::Engine.subclasses.map(&:instance).each { |engine| engine.eager_load! }
  ActiveRecord::Base.descendants
end

Which does not work.

I have both

  config.cache_classes = true
  config.eager_load = true

set in my environment.

I'm expecting there to be some sort of rails setting that does this - seems like a smart thing to do by default in production?


Solution

  • See https://github.com/rails/rails/issues/24133

    Rails 5 will have improvements, but you still currently need to do:

    # https://github.com/rails/rails/issues/24133
    ActiveSupport.on_load(:active_record) do
      con = ActiveRecord::Base.connection
      filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.dump")
    
      con.schema_cache.clear!
      con.data_sources.each { |table| con.schema_cache.add(table) }
      open(filename, 'wb') { |f| f.write(Marshal.dump(con.schema_cache)) }
    end
    

    in an initializer.