aboutsummaryrefslogtreecommitdiffstats
path: root/actionview/lib/action_view/digestor.rb
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2016-02-18 08:23:26 -0800
committerAaron Patterson <aaron.patterson@gmail.com>2016-02-18 08:23:26 -0800
commit3239ed48d28f3c0baf4445e6c279107e892b7cab (patch)
treea9860b5c54a42bd16615ae963341229f6c6698a8 /actionview/lib/action_view/digestor.rb
parent13c4cc3b5aea02716b7459c0da641438077f5236 (diff)
downloadrails-3239ed48d28f3c0baf4445e6c279107e892b7cab.tar.gz
rails-3239ed48d28f3c0baf4445e6c279107e892b7cab.tar.bz2
rails-3239ed48d28f3c0baf4445e6c279107e892b7cab.zip
move digest cache on to the DetailsKey object
This moves digest calculation cache on to the details key object. Before, the digest cache was a class level ivar, and one of the keys was the hash value of the details key object: https://github.com/rails/rails/blob/13c4cc3b5aea02716b7459c0da641438077f5236/actionview/lib/action_view/digestor.rb#L28 An object's hash value is not unique, so it's possible for this cache key to produce colliding keys with no resolution. This commit move cache on to the details key object itself, so we know that the digests are always unique per details key object.
Diffstat (limited to 'actionview/lib/action_view/digestor.rb')
-rw-r--r--actionview/lib/action_view/digestor.rb16
1 files changed, 7 insertions, 9 deletions
diff --git a/actionview/lib/action_view/digestor.rb b/actionview/lib/action_view/digestor.rb
index 657026fa14..f3c5d6c8df 100644
--- a/actionview/lib/action_view/digestor.rb
+++ b/actionview/lib/action_view/digestor.rb
@@ -4,13 +4,11 @@ require 'monitor'
module ActionView
class Digestor
- cattr_reader(:cache)
- @@cache = Concurrent::Map.new
@@digest_monitor = Monitor.new
class PerRequestDigestCacheExpiry < Struct.new(:app) # :nodoc:
def call(env)
- ActionView::Digestor.cache.clear
+ ActionView::LookupContext::DetailsKey.clear
app.call(env)
end
end
@@ -25,12 +23,12 @@ module ActionView
def digest(name:, finder:, **options)
options.assert_valid_keys(:dependencies, :partial)
- cache_key = ([ name, finder.details_key.hash ].compact + Array.wrap(options[:dependencies])).join('.')
+ cache_key = ([ name ].compact + Array.wrap(options[:dependencies])).join('.')
# this is a correctly done double-checked locking idiom
# (Concurrent::Map's lookups have volatile semantics)
- @@cache[cache_key] || @@digest_monitor.synchronize do
- @@cache.fetch(cache_key) do # re-check under lock
+ finder.digest_cache[cache_key] || @@digest_monitor.synchronize do
+ finder.digest_cache.fetch(cache_key) do # re-check under lock
compute_and_store_digest(cache_key, name, finder, options)
end
end
@@ -42,16 +40,16 @@ module ActionView
# Prevent re-entry or else recursive templates will blow the stack.
# There is no need to worry about other threads seeing the +false+ value,
# as they will then have to wait for this thread to let go of the @@digest_monitor lock.
- pre_stored = @@cache.put_if_absent(cache_key, false).nil? # put_if_absent returns nil on insertion
+ pre_stored = finder.digest_cache.put_if_absent(cache_key, false).nil? # put_if_absent returns nil on insertion
PartialDigestor
else
Digestor
end
- @@cache[cache_key] = stored_digest = klass.new(name, finder, options).digest
+ finder.digest_cache[cache_key] = stored_digest = klass.new(name, finder, options).digest
ensure
# something went wrong or ActionView::Resolver.caching? is false, make sure not to corrupt the @@cache
- @@cache.delete_pair(cache_key, false) if pre_stored && !stored_digest
+ finder.digest_cache.delete_pair(cache_key, false) if pre_stored && !stored_digest
end
end