diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2012-10-17 15:20:51 -0700 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2012-10-17 15:20:51 -0700 |
commit | 01149dd4f9b297b9f878c3ed752262d2ece37689 (patch) | |
tree | 2edf1f1cbbab3988ea0de5e17a41fdcba7f13d29 | |
parent | d410ac5136ee2c654b3922622bb2c270954acc9b (diff) | |
download | rails-01149dd4f9b297b9f878c3ed752262d2ece37689.tar.gz rails-01149dd4f9b297b9f878c3ed752262d2ece37689.tar.bz2 rails-01149dd4f9b297b9f878c3ed752262d2ece37689.zip |
fix Digestor to be thread safe.
Add a lock on the cache so that we don't have concurrency issues when
calculating the cache.
-rw-r--r-- | actionpack/lib/action_view/digestor.rb | 38 |
1 files changed, 30 insertions, 8 deletions
diff --git a/actionpack/lib/action_view/digestor.rb b/actionpack/lib/action_view/digestor.rb index f5852dbe73..1c6eaf36f7 100644 --- a/actionpack/lib/action_view/digestor.rb +++ b/actionpack/lib/action_view/digestor.rb @@ -1,3 +1,5 @@ +require 'mutex_m' + module ActionView class Digestor EXPLICIT_DEPENDENCY = /# Template Dependency: ([^ ]+)/ @@ -19,16 +21,30 @@ module ActionView /x cattr_reader(:cache) - @@cache = Hash.new + @@cache = Hash.new.extend Mutex_m def self.digest(name, format, finder, options = {}) - cache["#{name}.#{format}"] ||= new(name, format, finder, options).digest + cache.synchronize do + unsafe_digest name, format, finder, options + end end - attr_reader :name, :format, :finder, :options + ### + # This method is NOT thread safe. DO NOT CALL IT DIRECTLY, instead call + # Digestor.digest + def self.unsafe_digest(name, format, finder, options = {}) # :nodoc: + key = "#{name}.#{format}" - def initialize(name, format, finder, options = {}) - @name, @format, @finder, @options = name, format, finder, options + cache.fetch(key) do + klass = options[:partial] || name.include?("/_") ? PartialDigestor : Digestor + cache[key] = klass.new(name, format, finder).digest + end + end + + attr_reader :name, :format, :finder + + def initialize(name, format, finder) + @name, @format, @finder = name, format, finder end def digest @@ -48,7 +64,7 @@ module ActionView def nested_dependencies dependencies.collect do |dependency| - dependencies = Digestor.new(dependency, format, finder, partial: true).nested_dependencies + dependencies = PartialDigestor.new(dependency, format, finder).nested_dependencies dependencies.any? ? { dependency => dependencies } : dependency end end @@ -68,7 +84,7 @@ module ActionView end def partial? - options[:partial] || name.include?("/_") + false end def source @@ -77,7 +93,7 @@ module ActionView def dependency_digest dependencies.collect do |template_name| - Digestor.digest(template_name, format, finder, partial: true) + Digestor.unsafe_digest(template_name, format, finder, partial: true) end.join("-") end @@ -101,4 +117,10 @@ module ActionView source.scan(EXPLICIT_DEPENDENCY).flatten.uniq end end + + class PartialDigestor < Digestor # :nodoc: + def partial? + true + end + end end |