<% unless Rails.configuration.action_controller.perform_caching %><%= parameters.default %><% else key_key_s = hobo_cache_key(:views, route_on, query_params, attributes) cache_content = Rails.cache.read key_key_s unless cache_content.nil? Rails.logger.debug "CACHE HIT #{key_key_s}" cache_content, cache_ids = cache_content if scope.cache_ids # we have parent caches trying to generate their keys, so oblige them scope.cache_ids += Set.new(cache_ids) end %><%= raw cache_content %><% else Rails.logger.debug "CACHE MISS #{key_key_s}" # darn, cache is invalid. Now we have to generate our content and (re)generate our keys. unless scope.cache_ids # no parent caches so we need to set up the scope. scope.new_scope(:cache_ids => Set.new, :cache_stack => []) do %><%= cache_content=parameters.default %><% cache_ids = scope.cache_ids end else # we have a parent cache, so it has set up the scope. scope.cache_stack.push scope.cache_ids scope.cache_ids = Set.new %><%= cache_content=parameters.default %><% cache_ids = scope.cache_ids end dependencies = comma_split(dependencies) if dependencies.is_a?(String) dependencies ||= [this] dependencies.each do |dep| if dep.respond_to?(:typed_id) && dep.typed_id cache_ids << dep.typed_id elsif dep.respond_to?(:origin) && dep.origin cache_ids << "#{dep.origin.typed_id}:#{dep.origin_attribute}" elsif dep.respond_to?(:to_sym) cache_ids << dep.to_s elsif dep.respond_to?(:first) && dep.first.respond_to?(:typed_id) && dep.first.typed_id && dep.last.respond_to?(:to_sym) cache_ids << "#{dep.first.typed_id}:#{dep.last}" else fail "#{dep} not a Hobo model or not in database" end end if scope.cache_stack scope.cache_ids += scope.cache_stack.pop end cache_ids.each do |cache_id| # the database we're using must support atomically adding to a cache key # there are several possible ways of doing so. # transactions: supported by Infinispan and activerecord-cache # sets: Redis has a set datatype (SADD & friends) # regex read: munge the value onto the key and then store that instead. Then do a regex read to get all values if Hobo.stable_cache.respond_to?(:transaction) key = ActiveSupport::Cache.expand_cache_key(cache_id, :sweep_key) Hobo.stable_cache.transaction do l = Set.new(Hobo.stable_cache.read(key)) << key_key_s Rails.logger.debug "CACHE SWEEP KEY: #{cache_id} #{l.to_a}" Hobo.stable_cache.write(key, l.to_a) end elsif Hobo.stable_cache.respond_to?(:read_matched) key = ActiveSupport::Cache.expand_cache_key([cache_id, key_key_s], :sweep_key) Rails.logger.debug "CACHE SWEEP KEY: #{key}" Hobo.stable_cache.write(key, nil) else # TODO: add support for Redis key = ActiveSupport::Cache.expand_cache_key(cache_id, :sweep_key) Rails.logger.warn "WARNING! cache transactions not supported please fix before going to production" l = Set.new(Hobo.stable_cache.read(key)) << key_key_s Rails.logger.debug "CACHE SWEEP KEY: #{cache_id} #{l.to_a}" Hobo.stable_cache.write(key, l.to_a) end end # Also store cache_ids in case we ever have a parent who needs to regenerate their keys. We can give then them ours without regenerating. Rails.logger.debug "CACHE: #{key_key_s} -> content + ids #{cache_ids.to_a}" Rails.cache.write(key_key_s, [cache_content, cache_ids.to_a]) end end %>