From c37d47e30897762145835e66ae752cce924af01d Mon Sep 17 00:00:00 2001 From: Matthew Draper Date: Tue, 30 Sep 2014 01:32:42 +0930 Subject: Soften the lock requirements when eager_load is disabled We don't need to fully disable concurrent requests: just ensure that loads are performed in isolation. --- .../rails/application/default_middleware_stack.rb | 38 +++++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'railties/lib/rails/application') diff --git a/railties/lib/rails/application/default_middleware_stack.rb b/railties/lib/rails/application/default_middleware_stack.rb index 6f9ccec137..14ea073039 100644 --- a/railties/lib/rails/application/default_middleware_stack.rb +++ b/railties/lib/rails/application/default_middleware_stack.rb @@ -26,7 +26,35 @@ module Rails middleware.use ::Rack::Cache, rack_cache end - middleware.use ::Rack::Lock unless allow_concurrency? + if config.allow_concurrency == false + # User has explicitly opted out of concurrent request + # handling: presumably their code is not threadsafe + + middleware.use ::Rack::Lock + + elsif config.allow_concurrency + # Do nothing, even if we know this is dangerous + + else + # Default concurrency setting + + if config.cache_classes && config.eager_load + # No lock required + + elsif config.cache_classes + # The load interlock is required, but not a full request + # lock + + middleware.use ::ActionDispatch::LoadInterlock + + else + # If we're reloading on each request, they all need to be + # run in isolation + + middleware.use ::Rack::Lock + end + end + middleware.use ::Rack::Runtime middleware.use ::Rack::MethodOverride unless config.api_only middleware.use ::ActionDispatch::RequestId @@ -65,14 +93,6 @@ module Rails config.reload_classes_only_on_change != true || app.reloaders.map(&:updated?).any? end - def allow_concurrency? - if config.allow_concurrency.nil? - config.cache_classes && config.eager_load - else - config.allow_concurrency - end - end - def load_rack_cache rack_cache = config.action_dispatch.rack_cache return unless rack_cache -- cgit v1.2.3 From 383fed5f232630c198847ec573821ede4cf267a9 Mon Sep 17 00:00:00 2001 From: Matthew Draper Date: Tue, 30 Sep 2014 01:46:07 +0930 Subject: Rely on the load interlock for non-caching reloads, too --- .../rails/application/default_middleware_stack.rb | 22 +++++++--------------- railties/lib/rails/application/finisher.rb | 6 ++++-- 2 files changed, 11 insertions(+), 17 deletions(-) (limited to 'railties/lib/rails/application') diff --git a/railties/lib/rails/application/default_middleware_stack.rb b/railties/lib/rails/application/default_middleware_stack.rb index 14ea073039..88eade5c5a 100644 --- a/railties/lib/rails/application/default_middleware_stack.rb +++ b/railties/lib/rails/application/default_middleware_stack.rb @@ -32,26 +32,18 @@ module Rails middleware.use ::Rack::Lock - elsif config.allow_concurrency - # Do nothing, even if we know this is dangerous + elsif config.allow_concurrency == :unsafe + # Do nothing, even if we know this is dangerous. This is the + # historical behaviour for true. else - # Default concurrency setting + # Default concurrency setting: enabled, but safe - if config.cache_classes && config.eager_load - # No lock required - - elsif config.cache_classes - # The load interlock is required, but not a full request - # lock + unless config.cache_classes && config.eager_load + # Without cache_classes + eager_load, the load interlock + # is required for proper operation middleware.use ::ActionDispatch::LoadInterlock - - else - # If we're reloading on each request, they all need to be - # run in isolation - - middleware.use ::Rack::Lock end end diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb index 0599e988d9..f8f92792a7 100644 --- a/railties/lib/rails/application/finisher.rb +++ b/railties/lib/rails/application/finisher.rb @@ -86,8 +86,10 @@ module Rails # added in the hook are taken into account. initializer :set_clear_dependencies_hook, group: :all do callback = lambda do - ActiveSupport::DescendantsTracker.clear - ActiveSupport::Dependencies.clear + ActiveSupport::Dependencies.interlock.attempt_loading do + ActiveSupport::DescendantsTracker.clear + ActiveSupport::Dependencies.clear + end end if config.reload_classes_only_on_change -- cgit v1.2.3