PERF: ensure we warm up schema cache in the entire multisite

PERF: ensure we warm up schema cache in the entire multisite

This makes sure that all processes that fork off the master have a fully operation schema cache.

In Rails 6, schema cache is now bolted to the connection pool. This change ensures the cache on all pools is fully populated prior to forking.

The bolting of cache to connection pool does lead to some strange cases where a connection can “steal” the cache from another connection, which can cause stuff to possibly hang or deadlock. This change minimizes the risk of this happening cause it is already primed.

We make a STRONG assumption that the schema is always the same on all sites when we spin up a multisite cluster.

diff --git a/config/unicorn.conf.rb b/config/unicorn.conf.rb
index 85b2800..9b140ea 100644
--- a/config/unicorn.conf.rb
+++ b/config/unicorn.conf.rb
@@ -61,6 +61,23 @@ before_fork do |server, worker|
       table.classify.constantize.first rescue nil
     end
 
+    # ensure we have a full schema cache in case we missed something above
+    ActiveRecord::Base.connection.data_sources.each do |table|
+      ActiveRecord::Base.connection.schema_cache.add(table)
+    end
+
+    schema_cache = ActiveRecord::Base.connection.schema_cache
+
+    # load up schema cache for all multisite assuming all dbs have
+    # an identical schema
+    RailsMultisite::ConnectionManagement.each_connection do
+      dup_cache = schema_cache.dup
+      # this line is not really needed, but just in case the
+      # underlying implementation changes lets give it a shot
+      dup_cache.connection = nil
+      ActiveRecord::Base.connection.schema_cache = dup_cache
+    end
+
     # router warm up
     Rails.application.routes.recognize_path('abc') rescue nil

GitHub sha: e0a403ed

1 Like