REFACTOR: Move the multisite middleware to the front

REFACTOR: Move the multisite middleware to the front

Both request tracking and message bus rely on multisite before the middleware has run which is not ideal.

diff --git a/config/initializers/004-rails_multisite.rb b/config/initializers/004-rails_multisite.rb
deleted file mode 100644
index 2154349..0000000
--- a/config/initializers/004-rails_multisite.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-module RailsMultisite
-  class ConnectionManagement
-    def self.safe_each_connection
-      self.each_connection do |db|
-        begin
-          yield(db) if block_given?
-        rescue => e
-          STDERR.puts "URGENT: Failed to initialize site #{db}: "\
-            "#{e.class} #{e.message}\n#{e.backtrace.join("\n")}"
-
-          # the show must go on, don't stop startup if multisite fails
-        end
-      end
-    end
-  end
-
-  class DiscoursePatches
-    def self.config
-      {
-        db_lookup: lambda do |env|
-          env["PATH_INFO"] == "/srv/status" ? "default" : nil
-        end
-      }
-    end
-  end
-end
-
-if Rails.configuration.multisite
-  Rails.configuration.middleware.swap(
-    RailsMultisite::Middleware,
-    RailsMultisite::Middleware,
-    RailsMultisite::DiscoursePatches.config
-  )
-end
diff --git a/config/initializers/200-first_middlewares.rb b/config/initializers/200-first_middlewares.rb
new file mode 100644
index 0000000..6ae5816
--- /dev/null
+++ b/config/initializers/200-first_middlewares.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+# we want MesageBus to be close to the front
+# this is important cause the vast majority of web requests go to it
+# this allows us to avoid full middleware crawls each time
+#
+# We aren't manipulating the middleware stack directly because of
+# https://github.com/rails/rails/pull/27936
+session_operations = Rails::Configuration::MiddlewareStackProxy.new([
+   [:delete, MessageBus::Rack::Middleware],
+   [:unshift, MessageBus::Rack::Middleware],
+])
+
+Rails.configuration.middleware = Rails.configuration.middleware + session_operations
+
+# no reason to track this in development, that is 300+ redis calls saved per
+# page view (we serve all assets out of thin in development)
+if Rails.env != 'development' || ENV['TRACK_REQUESTS']
+  require 'middleware/request_tracker'
+  Rails.configuration.middleware.unshift Middleware::RequestTracker
+
+  if GlobalSetting.enable_performance_http_headers
+    MethodProfiler.ensure_discourse_instrumentation!
+  end
+end
+
+if Rails.configuration.multisite
+  # Multisite needs to be first, because the request tracker and message bus
+  # rely on it
+  session_operations = Rails::Configuration::MiddlewareStackProxy.new([
+     [:delete, RailsMultisite::Middleware],
+     [:unshift, RailsMultisite::Middleware, RailsMultisite::DiscoursePatches.config],
+  ])
+
+  Rails.configuration.middleware = Rails.configuration.middleware + session_operations
+end
diff --git a/config/initializers/200-message_bus_request_tracker.rb b/config/initializers/200-message_bus_request_tracker.rb
deleted file mode 100644
index c0ebcfc..0000000
--- a/config/initializers/200-message_bus_request_tracker.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-# we want MesageBus in the absolute front
-# this is important cause the vast majority of web requests go to it
-# this allows us to avoid full middleware crawls each time
-# Pending https://github.com/rails/rails/pull/27936
-session_operations = Rails::Configuration::MiddlewareStackProxy.new([
-   [:delete, MessageBus::Rack::Middleware],
-   [:unshift, MessageBus::Rack::Middleware],
-])
-
-Rails.configuration.middleware = Rails.configuration.middleware + session_operations
-
-# no reason to track this in development, that is 300+ redis calls saved per
-# page view (we serve all assets out of thin in development)
-if Rails.env != 'development' || ENV['TRACK_REQUESTS']
-  require 'middleware/request_tracker'
-  Rails.configuration.middleware.unshift Middleware::RequestTracker
-
-  if GlobalSetting.enable_performance_http_headers
-    MethodProfiler.ensure_discourse_instrumentation!
-  end
-end
diff --git a/lib/freedom_patches/rails_multisite.rb b/lib/freedom_patches/rails_multisite.rb
new file mode 100644
index 0000000..c4627da
--- /dev/null
+++ b/lib/freedom_patches/rails_multisite.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module RailsMultisite
+  class ConnectionManagement
+    def self.safe_each_connection
+      self.each_connection do |db|
+        begin
+          yield(db) if block_given?
+        rescue => e
+          STDERR.puts "URGENT: Failed to initialize site #{db}: "\
+            "#{e.class} #{e.message}\n#{e.backtrace.join("\n")}"
+
+          # the show must go on, don't stop startup if multisite fails
+        end
+      end
+    end
+  end
+
+  class DiscoursePatches
+    def self.config
+      {
+        db_lookup: lambda do |env|
+          env["PATH_INFO"] == "/srv/status" ? "default" : nil
+        end
+      }
+    end
+  end
+end
diff --git a/lib/middleware/request_tracker.rb b/lib/middleware/request_tracker.rb
index 41ad8a6..4fbe3d1 100644
--- a/lib/middleware/request_tracker.rb
+++ b/lib/middleware/request_tracker.rb
@@ -51,14 +51,6 @@ class Middleware::RequestTracker
     @app = app
   end
 
-  def self.log_request_on_site(data, host)
-    RailsMultisite::ConnectionManagement.with_hostname(host) do
-      unless Discourse.pg_readonly_mode?
-        log_request(data)
-      end
-    end
-  end
-
   def self.log_request(data)
     status = data[:status]
     track_view = data[:track_view]
@@ -135,7 +127,6 @@ class Middleware::RequestTracker
 
     # we got to skip this on error ... its just logging
     data = self.class.get_data(env, result, info) rescue nil
-    host = RailsMultisite::ConnectionManagement.host(env)
 
     if data
       if result && (headers = result[1])
@@ -146,7 +137,7 @@ class Middleware::RequestTracker
         @@detailed_request_loggers.each { |logger| logger.call(env, data) }
       end
 
-      log_later(data, host)
+      log_later(data)
     end
 
   end
@@ -296,10 +287,11 @@ class Middleware::RequestTracker
     end
   end
 
-  def log_later(data, host)
-    Scheduler::Defer.later("Track view", _db = nil) do
-      self.class.log_request_on_site(data, host)
+  def log_later(data)
+    Scheduler::Defer.later("Track view") do
+      unless Discourse.pg_readonly_mode?
+        self.class.log_request(data)
+      end
     end
   end
-
 end

GitHub sha: a91843f0

Revert “REFACTOR: Move the multisite middleware to the front”