From 6124eb02c63b666e640e778bf74380c3772926a0 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 7 Feb 2019 13:30:58 -0800 Subject: Split digest cache from details identity cache This commit splits the digest cache from the "details identity" cache. Now both caches can be managed independently. --- actionview/lib/action_view/lookup_context.rb | 29 ++++++++++++++++++------- actionview/lib/action_view/rendering.rb | 1 + actionview/test/template/resolver_cache_test.rb | 1 + actionview/test/template/test_case_test.rb | 4 ++++ 4 files changed, 27 insertions(+), 8 deletions(-) (limited to 'actionview') diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb index c3bb0a49fc..0387fd0e83 100644 --- a/actionview/lib/action_view/lookup_context.rb +++ b/actionview/lib/action_view/lookup_context.rb @@ -55,25 +55,36 @@ module ActionView register_detail(:handlers) { Template::Handlers.extensions } class DetailsKey #:nodoc: + alias :eql? :equal? @details_keys = Concurrent::Map.new + @digest_cache = Concurrent::Map.new + + def self.digest_cache(details) + if details[:formats] + details = details.dup + details[:formats] &= Template::Types.symbols + end + @digest_cache[details] ||= Concurrent::Map.new + end - def self.get(details) + def self.details_cache_key(details) if details[:formats] details = details.dup details[:formats] &= Template::Types.symbols end - @details_keys[details] ||= Concurrent::Map.new + @details_keys[details] ||= Object.new end def self.clear @view_context_class = nil @details_keys.clear + @digest_cache.clear end def self.digest_caches - @details_keys.values + @digest_cache.values end def self.view_context_class(klass) @@ -88,7 +99,7 @@ module ActionView # Calculate the details key. Remove the handlers from calculation to improve performance # since the user cannot modify it explicitly. def details_key #:nodoc: - @details_key ||= DetailsKey.get(@details) if @cache + @details_key ||= DetailsKey.details_cache_key(@details) if @cache end # Temporary skip passing the details_key forward. @@ -102,7 +113,8 @@ module ActionView private def _set_detail(key, value) # :doc: - @details = @details.dup if @details_key + @details = @details.dup if @digest_cache || @details_key + @digest_cache = nil @details_key = nil @details[key] = value end @@ -178,7 +190,7 @@ module ActionView user_details = @details.merge(options) if @cache - details_key = DetailsKey.get(user_details) + details_key = DetailsKey.details_cache_key(user_details) else details_key = nil end @@ -205,7 +217,7 @@ module ActionView end if @cache - [details, DetailsKey.get(details)] + [details, DetailsKey.details_cache_key(details)] else [details, nil] end @@ -236,6 +248,7 @@ module ActionView def initialize(view_paths, details = {}, prefixes = []) @details_key = nil + @digest_cache = nil @cache = true @prefixes = prefixes @rendered_format = nil @@ -245,7 +258,7 @@ module ActionView end def digest_cache - details_key + @digest_cache ||= DetailsKey.digest_cache(@details) end def initialize_details(target, details) diff --git a/actionview/lib/action_view/rendering.rb b/actionview/lib/action_view/rendering.rb index cf7d1105e0..da92ce1f5e 100644 --- a/actionview/lib/action_view/rendering.rb +++ b/actionview/lib/action_view/rendering.rb @@ -87,6 +87,7 @@ module ActionView # Returns an object that is able to render templates. def view_renderer # :nodoc: + # Lifespan: Per controller @_view_renderer ||= ActionView::Renderer.new(lookup_context) end diff --git a/actionview/test/template/resolver_cache_test.rb b/actionview/test/template/resolver_cache_test.rb index 8a5db1346a..90b61a2aa1 100644 --- a/actionview/test/template/resolver_cache_test.rb +++ b/actionview/test/template/resolver_cache_test.rb @@ -4,6 +4,7 @@ require "abstract_unit" class ResolverCacheTest < ActiveSupport::TestCase def test_inspect_shields_cache_internals + ActionView::LookupContext::DetailsKey.clear assert_match %r(#>), ActionView::Resolver.new.inspect end end diff --git a/actionview/test/template/test_case_test.rb b/actionview/test/template/test_case_test.rb index ab3ababba4..4d3338e637 100644 --- a/actionview/test/template/test_case_test.rb +++ b/actionview/test/template/test_case_test.rb @@ -24,6 +24,10 @@ module ActionView DeveloperStruct = Struct.new(:name) module SharedTests + def setup + ActionView::LookupContext::DetailsKey.clear + end + def self.included(test_case) test_case.class_eval do test "helpers defined on ActionView::TestCase are available" do -- cgit v1.2.3 From f369b63ad69ac8bb29811e145a148dd109de777c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 8 Feb 2019 14:43:22 -0800 Subject: Teach DetailsKey how to clear the template cache This commit exposes all system wide view paths so that we can clear their caches. --- actionview/lib/action_view/lookup_context.rb | 4 ++++ actionview/lib/action_view/view_paths.rb | 26 ++++++++++++++++++++++- actionview/test/template/log_subscriber_test.rb | 4 ++-- actionview/test/template/render_test.rb | 11 +++++----- actionview/test/template/streaming_render_test.rb | 4 ++-- 5 files changed, 38 insertions(+), 11 deletions(-) (limited to 'actionview') diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb index 0387fd0e83..1cc0a55c31 100644 --- a/actionview/lib/action_view/lookup_context.rb +++ b/actionview/lib/action_view/lookup_context.rb @@ -78,6 +78,10 @@ module ActionView end def self.clear + ActionView::ViewPaths.all_view_paths.each do |path_set| + path_set.each(&:clear_cache) + end + ActionView::LookupContext.fallbacks.each(&:clear_cache) @view_context_class = nil @details_keys.clear @digest_cache.clear diff --git a/actionview/lib/action_view/view_paths.rb b/actionview/lib/action_view/view_paths.rb index d5694d77f4..3ca5aedc14 100644 --- a/actionview/lib/action_view/view_paths.rb +++ b/actionview/lib/action_view/view_paths.rb @@ -5,13 +5,21 @@ module ActionView extend ActiveSupport::Concern included do - class_attribute :_view_paths, default: ActionView::PathSet.new.freeze + ViewPaths.set_view_paths(self, ActionView::PathSet.new.freeze) end delegate :template_exists?, :any_templates?, :view_paths, :formats, :formats=, :locale, :locale=, to: :lookup_context module ClassMethods + def _view_paths + ViewPaths.get_view_paths(self) + end + + def _view_paths=(paths) + ViewPaths.set_view_paths(self, paths) + end + def _prefixes # :nodoc: @_prefixes ||= begin return local_prefixes if superclass.abstract? @@ -29,6 +37,22 @@ module ActionView end end + # :stopdoc: + @all_view_paths = {} + + def self.get_view_paths(klass) + @all_view_paths[klass] || get_view_paths(klass.superclass) + end + + def self.set_view_paths(klass, paths) + @all_view_paths[klass] = paths + end + + def self.all_view_paths + @all_view_paths.values.uniq + end + # :startdoc: + # The prefixes used in render "foo" shortcuts. def _prefixes # :nodoc: self.class._prefixes diff --git a/actionview/test/template/log_subscriber_test.rb b/actionview/test/template/log_subscriber_test.rb index 4574b798d9..83bb651ea3 100644 --- a/actionview/test/template/log_subscriber_test.rb +++ b/actionview/test/template/log_subscriber_test.rb @@ -11,9 +11,9 @@ class AVLogSubscriberTest < ActiveSupport::TestCase def setup super + ActionView::LookupContext::DetailsKey.clear + view_paths = ActionController::Base.view_paths - view_paths.each(&:clear_cache) - ActionView::LookupContext.fallbacks.each(&:clear_cache) lookup_context = ActionView::LookupContext.new(view_paths, {}, ["test"]) renderer = ActionView::Renderer.new(lookup_context) diff --git a/actionview/test/template/render_test.rb b/actionview/test/template/render_test.rb index b8d8717db4..bbecc404be 100644 --- a/actionview/test/template/render_test.rb +++ b/actionview/test/template/render_test.rb @@ -631,9 +631,8 @@ class CachedViewRenderTest < ActiveSupport::TestCase # Ensure view path cache is primed def setup + ActionView::LookupContext::DetailsKey.clear view_paths = ActionController::Base.view_paths - view_paths.each(&:clear_cache) - ActionView::LookupContext.fallbacks.each(&:clear_cache) assert_equal ActionView::OptimizedFileSystemResolver, view_paths.first.class setup_view(view_paths) end @@ -650,9 +649,9 @@ class LazyViewRenderTest < ActiveSupport::TestCase # Test the same thing as above, but make sure the view path # is not eager loaded def setup + ActionView::LookupContext::DetailsKey.clear + view_paths = ActionController::Base.view_paths - view_paths.each(&:clear_cache) - ActionView::LookupContext.fallbacks.each(&:clear_cache) path = ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH) view_paths = ActionView::PathSet.new([path]) assert_equal ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH), view_paths.first @@ -710,10 +709,10 @@ class CachedCollectionViewRenderTest < ActiveSupport::TestCase # Ensure view path cache is primed setup do + ActionView::LookupContext::DetailsKey.clear + view_paths = ActionController::Base.view_paths assert_equal ActionView::OptimizedFileSystemResolver, view_paths.first.class - view_paths.each(&:clear_cache) - ActionView::LookupContext.fallbacks.each(&:clear_cache) ActionView::PartialRenderer.collection_cache = ActiveSupport::Cache::MemoryStore.new diff --git a/actionview/test/template/streaming_render_test.rb b/actionview/test/template/streaming_render_test.rb index 4567ee31b4..a5b59a700e 100644 --- a/actionview/test/template/streaming_render_test.rb +++ b/actionview/test/template/streaming_render_test.rb @@ -7,9 +7,9 @@ end class SetupFiberedBase < ActiveSupport::TestCase def setup + ActionView::LookupContext::DetailsKey.clear + view_paths = ActionController::Base.view_paths - view_paths.each(&:clear_cache) - ActionView::LookupContext.fallbacks.each(&:clear_cache) @assigns = { secret: "in the sauce", name: nil } @view = ActionView::Base.with_empty_template_cache.with_view_paths(view_paths, @assigns) -- cgit v1.2.3 From 6ccddadd847c2c3106867ca8085b51a82b449e14 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 8 Feb 2019 15:16:00 -0800 Subject: reuse details cache key identity object --- actionview/lib/action_view/lookup_context.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'actionview') diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb index 1cc0a55c31..f0099a9ade 100644 --- a/actionview/lib/action_view/lookup_context.rb +++ b/actionview/lib/action_view/lookup_context.rb @@ -62,11 +62,7 @@ module ActionView @digest_cache = Concurrent::Map.new def self.digest_cache(details) - if details[:formats] - details = details.dup - details[:formats] &= Template::Types.symbols - end - @digest_cache[details] ||= Concurrent::Map.new + @digest_cache[details_cache_key(details)] ||= Concurrent::Map.new end def self.details_cache_key(details) -- cgit v1.2.3 From 0efc609ac62077b38297c13ef212d5c04588869d Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 8 Feb 2019 15:17:02 -0800 Subject: Always call super --- actionview/lib/action_view/lookup_context.rb | 1 - actionview/test/template/render_test.rb | 2 -- actionview/test/template/test_case_test.rb | 1 + 3 files changed, 1 insertion(+), 3 deletions(-) (limited to 'actionview') diff --git a/actionview/lib/action_view/lookup_context.rb b/actionview/lib/action_view/lookup_context.rb index f0099a9ade..61fe11cf45 100644 --- a/actionview/lib/action_view/lookup_context.rb +++ b/actionview/lib/action_view/lookup_context.rb @@ -55,7 +55,6 @@ module ActionView register_detail(:handlers) { Template::Handlers.extensions } class DetailsKey #:nodoc: - alias :eql? :equal? @details_keys = Concurrent::Map.new diff --git a/actionview/test/template/render_test.rb b/actionview/test/template/render_test.rb index bbecc404be..3f298d81f3 100644 --- a/actionview/test/template/render_test.rb +++ b/actionview/test/template/render_test.rb @@ -650,8 +650,6 @@ class LazyViewRenderTest < ActiveSupport::TestCase # is not eager loaded def setup ActionView::LookupContext::DetailsKey.clear - - view_paths = ActionController::Base.view_paths path = ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH) view_paths = ActionView::PathSet.new([path]) assert_equal ActionView::FileSystemResolver.new(FIXTURE_LOAD_PATH), view_paths.first diff --git a/actionview/test/template/test_case_test.rb b/actionview/test/template/test_case_test.rb index 4d3338e637..c89aff9c9d 100644 --- a/actionview/test/template/test_case_test.rb +++ b/actionview/test/template/test_case_test.rb @@ -26,6 +26,7 @@ module ActionView module SharedTests def setup ActionView::LookupContext::DetailsKey.clear + super end def self.included(test_case) -- cgit v1.2.3