aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/plugins/interlock/lib
diff options
context:
space:
mode:
authorHenare Degan <henare.degan@gmail.com>2012-12-09 19:08:59 +1100
committerHenare Degan <henare.degan@gmail.com>2012-12-11 11:09:38 +1100
commit64a93911ebae4eaa2a1bc2b9e09d1468d77aadb9 (patch)
treec4515ab64e30bb45c34aff04bf34066ab0c6c5bf /vendor/plugins/interlock/lib
parent0d533ce1d56e1ec1446774cc6fff52451a844f3f (diff)
Remove interlock as it's not compatible with Rails 3 and is unmaintained
Diffstat (limited to 'vendor/plugins/interlock/lib')
-rw-r--r--vendor/plugins/interlock/lib/interlock.rb28
-rw-r--r--vendor/plugins/interlock/lib/interlock/action_controller.rb253
-rw-r--r--vendor/plugins/interlock/lib/interlock/action_view.rb98
-rw-r--r--vendor/plugins/interlock/lib/interlock/active_record.rb61
-rw-r--r--vendor/plugins/interlock/lib/interlock/config.rb168
-rw-r--r--vendor/plugins/interlock/lib/interlock/core_extensions.rb74
-rw-r--r--vendor/plugins/interlock/lib/interlock/finders.rb155
-rw-r--r--vendor/plugins/interlock/lib/interlock/interlock.rb155
-rw-r--r--vendor/plugins/interlock/lib/interlock/lock.rb44
-rw-r--r--vendor/plugins/interlock/lib/interlock/pass_through_store.rb19
-rw-r--r--vendor/plugins/interlock/lib/tasks/interlock.rake10
11 files changed, 0 insertions, 1065 deletions
diff --git a/vendor/plugins/interlock/lib/interlock.rb b/vendor/plugins/interlock/lib/interlock.rb
deleted file mode 100644
index e4cfb91c3..000000000
--- a/vendor/plugins/interlock/lib/interlock.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-
-module Interlock
-end
-
-require 'interlock/core_extensions'
-require 'interlock/config'
-require 'interlock/interlock'
-require 'interlock/lock'
-require 'interlock/pass_through_store'
-require 'interlock/action_controller'
-require 'interlock/action_view'
-require 'interlock/finders'
-require 'interlock/active_record'
-
-begin
- if defined?(JRUBY_VERSION)
- require 'memcache-client'
- else
- require 'memcached'
- end
-rescue LoadError
-end
-
-unless ActionController::Base.perform_caching
- RAILS_DEFAULT_LOGGER.warn "** interlock warning; config.perform_caching == false"
-end
-
-Interlock::Config.run!
diff --git a/vendor/plugins/interlock/lib/interlock/action_controller.rb b/vendor/plugins/interlock/lib/interlock/action_controller.rb
deleted file mode 100644
index 73ed81843..000000000
--- a/vendor/plugins/interlock/lib/interlock/action_controller.rb
+++ /dev/null
@@ -1,253 +0,0 @@
-
-module ActionController #:nodoc:
- class Base
-
-
-=begin rdoc
-Build the fragment key from a particular context. This must be deterministic and stateful except for the tag. We can't scope the key to arbitrary params because the view doesn't have access to which are relevant and which are not.
-
-Note that the tag can be pretty much any object. Define <tt>to_interlock_tag</tt> if you need custom tagging for some class. ActiveRecord::Base already has it defined appropriately.
-
-If you pass an Array of symbols as the tag, it will get value-mapped onto params and sorted. This makes granular scoping easier, although it doesn't sidestep the normal blanket invalidations.
-=end
-
- def caching_key(ignore = nil, tag = nil)
- ignore = Array(ignore)
- ignore = Interlock::SCOPE_KEYS if ignore.include? :all
-
- if (Interlock::SCOPE_KEYS - ignore).empty? and !tag
- raise Interlock::UsageError, "You must specify a :tag if you are ignoring the entire default scope."
- end
-
- if tag.is_a? Array and tag.all? {|x| x.is_a? Symbol}
- tag = tag.sort_by do |key|
- key.to_s
- end.map do |key|
- params[key].to_interlock_tag
- end.join(";")
- end
-
- Interlock.caching_key(
- ignore.include?(:controller) ? 'any' : controller_name,
- ignore.include?(:action) ? 'any' : action_name,
- ignore.include?(:id) ? 'all' : params[:id],
- tag
- )
- end
-
-
-=begin rdoc
-
-<tt>behavior_cache</tt> marks a controller block for caching. It accepts a list of class dependencies for invalidation, as well as as <tt>:tag</tt> and <tt>:ignore</tt> keys for explicit fragment scoping. It does not accept a <tt>:ttl</tt> key.
-
-Please note that the behavior of nested <tt>behavior_cache</tt> blocks is undefined.
-
-== Declaring dependencies
-
-You can declare non-default invalidation dependencies by passing models to <tt>behavior_cache</tt> (you can also pass them to <tt>view_cache</tt>, but you should only do that if you are caching a fragment without an associated behavior block in the controller).
-
-<b>No dependencies (cache never invalidates):</b>
- behavior_cache nil do
- end
-
-<b>Invalidate on any Media change:</b>
- behavior_cache Media do
- end
-
-<b>Invalidate on any Media or Item change:</b>
- behavior_cache Media, Item do
- end
-
-<b>Invalidate on Item changes if the Item <tt>id</tt> matches the current <tt>params[:id]</tt> value:</b>
- behavior_cache Item => :id do
- end
-
-You do not have to pass the same dependencies to <tt>behavior_cache</tt> and <tt>view_cache</tt> even for the same action. The set union of both dependency lists will be used.
-
-== Narrowing scope and caching multiple blocks
-
-Sometimes you need to cache multiple blocks in a controller, or otherwise get a more fine-grained scope. Interlock provides the <tt>:tag</tt> key for this purpose. <tt>:tag</tt> accepts either an array of symbols, which are mapped to <tt>params</tt> values, or an arbitrary object, which is converted to a string identifier. <b>Your corresponding behavior caches and view caches must have identical <tt>:tag</tt> values for the interlocking to take effect.</b>
-
-Note that <tt>:tag</tt> can be used to scope caches. You can simultaneously cache different versions of the same block, differentiating based on params or other logic. This is great for caching per-user, for example:
-
- def profile
- @user = current_user
- behavior_cache :tag => @user do
- @items = @user.items
- end
- end
-
-In the view, use the same <tt>:tag</tt> value (<tt>@user</tt>). Note that <tt>@user</tt> must be set outside of the behavior block in the controller, because its contents are used to decide whether to run the block in the first place.
-
-This way each user will see only their own cache. Pretty neat.
-
-== Broadening scope
-
-Sometimes the default scope (<tt>controller</tt>, <tt>action</tt>, <tt>params[:id]</tt>) is too narrow. For example, you might share a partial across actions, and set up its data via a filter. By default, Interlock will cache a separate version of it for each action. To avoid this, you can use the <tt>:ignore</tt> key, which lets you list parts of the default scope to ignore:
-
- before_filter :recent
-
- private
-
- def recent
- behavior_cache :ignore => :action do
- @recent = Item.find(:all, :limit => 5, :order => 'updated_at DESC')
- end
- end
-
-Valid values for <tt>:ignore</tt> are <tt>:controller</tt>, <tt>:action</tt>, <tt>:id</tt>, and <tt>:all</tt>. You can pass an array of multiple values. <b>Just like with <tt>:tag</tt>, your corresponding behavior caches and view caches must have identical <tt>:ignore</tt> values.</b> Note that cache blocks with <tt>:ignore</tt> values still obey the regular invalidation rules.
-
-A good way to get started is to just use the default scope. Then <tt>grep</tt> in the production log for <tt>interlock</tt> and see what keys are being set and read. If you see lots of different keys go by for data that you know is the same, then set some <tt>:ignore</tt> values.
-
-== Skipping caching
-
-You can pass <tt>:perform => false</tt> to disable caching, for example, in a preview action. Note that <tt>:perform</tt> only responds to <tt>false</tt>, not <tt>nil</tt>. This allows for handier view reuse because you can set <tt>:perform</tt> to an instance variable and it will still cache if the instance variable is not set:
-
- def preview
- @perform = false
- behavior_cache :perform => @perform do
- end
- render :action => 'show'
- end
-
-And in the <tt>show.html.erb</tt> view:
-
- <% view_cache :perform => @perform do %>
- <% end %>
-
-=end
-
- def behavior_cache(*args)
- conventional_class = begin; controller_name.classify.constantize; rescue NameError; end
- options, dependencies = Interlock.extract_options_and_dependencies(args, conventional_class)
-
- raise Interlock::UsageError, ":ttl has no effect in a behavior_cache block" if options[:ttl]
-
- Interlock.say "key", "yo: #{options.inspect} -- #{dependencies.inspect}"
-
- key = caching_key(options.value_for_indifferent_key(:ignore), options.value_for_indifferent_key(:tag))
-
- if options[:perform] == false || Interlock.config[:disabled]
- Interlock.say key, "is not cached"
- yield
- else
- Interlock.register_dependencies(dependencies, key)
-
- # See if the fragment exists, and run the block if it doesn't.
- unless read_fragment(key, :assign_content_for => false)
- Interlock.say key, "is running the controller block"
- yield
- end
- end
- end
-
- #:stopdoc:
- alias :caching :behavior_cache # Deprecated
- #:startdoc:
-
- private
-
- #
- # Callback to reset the local cache.
- #
- def clear_interlock_local_cache
- Interlock.local_cache = ::ActiveSupport::Cache::MemoryStore.new
- Interlock.log "** cleared interlock local cache"
- end
-
- # Should be registered first in the chain
- prepend_before_filter :clear_interlock_local_cache
-
- end
-
- module Caching #:nodoc:
- module Fragments
-
- #
- # Replaces Rail's write_fragment method. Avoids extra checks for regex keys
- # which are unsupported, adds more detailed logging information, stores writes
- # in the local process cache too to avoid duplicate memcached requests, and
- # includes the content_for cache in the fragment.
- #
- def write_fragment(key, block_content, options = nil)
- return unless perform_caching
-
- content = [block_content, @template.cached_content_for]
-
- cache_store.write(key, content, options)
- Interlock.local_cache.write(key, content, options)
-
- Interlock.say key, "wrote"
-
- block_content
- end
-
- #
- # Replaces Rail's read_fragment method. Avoids checks for regex keys,
- # which are unsupported, adds more detailed logging information, checks
- # the local process cache before hitting memcached, and restores the
- # content_for cache. Hits on memcached are also stored back locally to
- # avoid duplicate requests.
- #
- def read_fragment(key, options = nil)
- return unless perform_caching
-
- begin
- if content = Interlock.local_cache.read(key, options)
- # Interlock.say key, "read from local cache"
- elsif content = cache_store.read(key, options)
- raise Interlock::FragmentConsistencyError, "#{key} expected Array but got #{content.class}" unless content.is_a? Array
- Interlock.say key, "read from memcached"
- Interlock.local_cache.write(key, content, options)
- else
- # Not found
- return nil
- end
-
- raise Interlock::FragmentConsistencyError, "#{key}::content expected String but got #{content.first.class}" unless content.first.is_a? String
-
- options ||= {}
- # Note that 'nil' is considered true for :assign_content_for
- if options[:assign_content_for] != false and content.last
- # Extract content_for variables
- content.last.each do |name, value|
- raise Interlock::FragmentConsistencyError, "#{key}::content_for(:#{name}) expected String but got #{value.class}" unless value.is_a? String
- # We'll just call the helper because that will handle nested view_caches properly.
- @template.send(:content_for, name, value)
- end
- end
-
- content.first
- rescue Interlock::FragmentConsistencyError => e
- # Delete the bogus key
- Interlock.invalidate(key)
- # Reraise the error
- raise e
- end
- end
-
- end
-
- # With Rails 2.1 action caching, we need to slip in our :expire param into the ActionCacheFilter options, so that when we
- # write_fragment we can pass that in and allow shane's #{key}_expiry to take effect
- # (see def write in interlock/config.rb)
- module Actions
-
- module ClassMethods
- def caches_action(*actions)
- return unless cache_configured?
- options = actions.extract_options!
- around_filter(ActionCacheFilter.new(:cache_path => options.delete(:cache_path), :expire => options.delete(:expire)), {:only => actions}.merge(options))
- end
- end
-
- class ActionCacheFilter #:nodoc:
- def after(controller)
- return if controller.rendered_action_cache || !caching_allowed(controller)
- controller.write_fragment(controller.action_cache_path.path, controller.response.body, :expire => @options[:expire]) # pass in our :expire
- end
- end
- end
-
- end
-end
diff --git a/vendor/plugins/interlock/lib/interlock/action_view.rb b/vendor/plugins/interlock/lib/interlock/action_view.rb
deleted file mode 100644
index 12497b2ef..000000000
--- a/vendor/plugins/interlock/lib/interlock/action_view.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-
-module ActionView #:nodoc:
- class Base #:nodoc:
- attr_accessor :cached_content_for
- end
-
- module Helpers #:nodoc:
- module CacheHelper
-
-=begin rdoc
-
-<tt>view_cache</tt> marks a corresponding view block for caching. It accepts <tt>:tag</tt> and <tt>:ignore</tt> keys for explicit scoping, as well as a <tt>:ttl</tt> key and a <tt>:perform</tt> key.
-
-You can specify dependencies in <tt>view_cache</tt> if you really want to. Note that unlike <tt>behavior_cache</tt>, <tt>view_cache</tt> doesn't set up any default dependencies.
-
-Nested <tt>view_cache</tt> blocks work fine. You would only need to nest if you had a slowly invalidating block contained in a more quickly invalidating block; otherwise there's no benefit.
-
-Finally, caching <tt>content_for</tt> within a <tt>view_cache</tt> works, unlike regular Rails. It even works in nested caches.
-
-== Setting a TTL
-
-Use the <tt>:ttl</tt> key to specify a maximum time-to-live, in seconds:
-
- <% view_cache :ttl => 5.minutes do %>
- <% end %>
-
-Note that the cached item is not guaranteed to live this long. An invalidation rule could trigger first, or memcached could eject the item early due to the LRU.
-
-== View caching without action caching
-
-It's fine to use a <tt>view_cache</tt> block without a <tt>behavior_cache</tt> block. For example, to mimic regular fragment cache behavior, but take advantage of memcached's <tt>:ttl</tt> support, call:
-
- <% view_cache :ignore => :all, :tag => 'sidebar', :ttl => 5.minutes do %>
- <% end %>
-
-== Dependencies, scoping, and other options
-
-See ActionController::Base for explanations of the rest of the options. The <tt>view_cache</tt> and <tt>behavior_cache</tt> APIs are identical except for setting the <tt>:ttl</tt>, which can only be done in the view, and the default dependency, which is only set by <tt>behavior_cache</tt>.
-
-=end
- def view_cache(*args, &block)
- # conventional_class = begin; controller.controller_name.classify.constantize; rescue NameError; end
- options, dependencies = Interlock.extract_options_and_dependencies(args, nil)
-
- key = controller.caching_key(options.value_for_indifferent_key(:ignore), options.value_for_indifferent_key(:tag))
-
- if options[:perform] == false || Interlock.config[:disabled]
- # Interlock.say key, "is not cached"
- block.call
- else
- Interlock.register_dependencies(dependencies, key)
-
- # Interlock.say key, "is rendering"
-
- @cached_content_for, previous_cached_content_for = {}, @cached_content_for
-
- cache key, :ttl => (options.value_for_indifferent_key(:ttl) or Interlock.config[:ttl]), &block
-
- # This is tricky. If we were already caching content_fors in a parent block, we need to
- # append the content_fors set in the inner block to those already set in the outer block.
- if previous_cached_content_for
- @cached_content_for.each do |key, value|
- previous_cached_content_for[key] = "#{previous_cached_content_for[key]}#{value}"
- end
- end
-
- # Restore the cache state
- @cached_content_for = previous_cached_content_for
- end
- end
-
- #:stopdoc:
- alias :caching :view_cache # Deprecated
- #:startdoc:
-
- end
-
-
- module CaptureHelper
- #
- # Override content_for so we can cache the instance variables it sets along with the fragment.
- #
- def content_for(name, content = nil, &block)
- ivar = "@content_for_#{name}"
- existing_content = instance_variable_get(ivar).to_s
- this_content = (block_given? ? capture(&block) : content)
-
- # If we are in a view_cache block, cache what we added to this instance variable
- if @cached_content_for
- @cached_content_for[name] = "#{@cached_content_for[name]}#{this_content}"
- end
-
- instance_variable_set(ivar, existing_content + this_content)
- end
- end
-
- end
-end
diff --git a/vendor/plugins/interlock/lib/interlock/active_record.rb b/vendor/plugins/interlock/lib/interlock/active_record.rb
deleted file mode 100644
index 16a448aaa..000000000
--- a/vendor/plugins/interlock/lib/interlock/active_record.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-
-module ActiveRecord #:nodoc:
- class Base
-
- @@nil_sentinel = :_nil
-
- class << self # Class methods
- def update_counters_with_expiry(id, counters)
- update_counters_without_expiry(id, counters)
- find(id).expire_interlock_keys
- end
- alias_method_chain :update_counters, :expiry
- end
-
- #
- # Convert this record to a tag string.
- #
- def to_interlock_tag
- "#{self.class.name}-#{self.id}".escape_tag_fragment
- end
-
- #
- # The expiry callback.
- #
- def expire_interlock_keys
- return if Interlock.config[:disabled] or (defined? CGI::Session::ActiveRecordStore and is_a? CGI::Session::ActiveRecordStore::Session)
-
- # Fragments
- self.expire_interlock_keys_for_dependency(Interlock.dependency_key(self.class.base_class, :all, nil))
- self.expire_interlock_keys_for_dependency(Interlock.dependency_key(self.class.base_class, :id, "::::#{to_param}:"))
-
- # Models
- if Interlock.config[:with_finders]
- key = self.class.base_class.caching_key(self.id)
- Interlock.say key, 'invalidated with finders', 'model'
- Interlock.invalidate key
- end
- end
-
- before_save :expire_interlock_keys
- after_save :expire_interlock_keys
- after_destroy :expire_interlock_keys
-
- #
- # Reload. Expires the cache and force reload from db.
- #
- def reload_with_expiry(*args)
- expire_interlock_keys
- reload_without_expiry(*args)
- end
- alias_method_chain :reload, :expiry
-
- def expire_interlock_keys_for_dependency(dependency_key)
- (CACHE.get(dependency_key) || {}).each do |key, scope|
- Interlock.say key, "invalidated by rule #{self.class} -> #{scope.inspect}."
- Interlock.invalidate key
- end
- end
-
- end
-end
diff --git a/vendor/plugins/interlock/lib/interlock/config.rb b/vendor/plugins/interlock/lib/interlock/config.rb
deleted file mode 100644
index 956002dd5..000000000
--- a/vendor/plugins/interlock/lib/interlock/config.rb
+++ /dev/null
@@ -1,168 +0,0 @@
-#require 'ehcache'
-module Interlock
-
- DEFAULTS = {
- :ttl => 1.day,
- :namespace => 'app',
- :servers => ['127.0.0.1:11211'],
- :client => 'memcache-client',
- :with_finders => false
- }
-
- CLIENT_KEYS =[
- :prefix_key,
- :distribution,
- :verify_key,
- :tcp_nodelay,
- :hash,
- :hash_with_prefix_key,
- :show_backtraces,
- :default_ttl,
- :ketama_weighted,
- :retry_timeout,
- :default_weight,
- :buffer_requests,
- :timeout,
- :sort_hosts,
- :cache_lookups,
- :connect_timeout,
- :no_block,
- :failover,
- :support_cas,
- :namespace
- ]
-
- mattr_accessor :config
- @@config = DEFAULTS
-
- module Config
-
- CONFIG_FILE = "#{RAILS_ROOT}/config/memcached.yml"
-
- class << self
-
- #
- # Load the configuration file, if available, and then set up the Memcached instance,
- # Rails settings, and CACHE constants. Should be more or less compatible with
- # Cache_fu.
- #
- def run!
- if File.exist?(CONFIG_FILE)
- template = ERB.new(File.open(CONFIG_FILE) {|f| f.read})
- config = YAML.load(template.result(binding))
- config.deep_symbolize_keys!
-
- Interlock.config.merge!(config[:defaults] || {})
- Interlock.config.merge!(config[RAILS_ENV.to_sym] || {})
- end
-
- install_memcached
- install_fragments
-
- # Always install the finders.
- install_finders if Interlock.config[:with_finders]
- end
-
- #
- # Configure memcached for this app.
- #
- def install_memcached
- Interlock.config[:namespace] << "-#{RAILS_ENV}"
-
- unless defined? Object::CACHE
-
- # Give people a choice of client, even though I don't like conditional dependencies.
- klass = case Interlock.config[:client]
- when 'memcached'
- begin
- Memcached::Rails
- rescue ArgumentError
- raise ConfigurationError, "'memcached' client requested but not installed. Try 'sudo gem install memcached'."
- end
-
- when 'memcache-client'
- begin
- if MemCache.constants.include?('SVNURL')
- raise ConfigurationError, "You have the Ruby-MemCache gem installed. Please uninstall Ruby-MemCache, or otherwise guarantee that memcache-client will load instead."
- end
- MemCache
- rescue ArgumentError
- raise ConfigurationError, "'memcache-client' client requested but not installed. Try 'sudo gem install memcache-client'."
- end
- end
-
- Object.const_set('CACHE',
- klass.new(
- Interlock.config[:servers],
- Interlock.config.slice(*CLIENT_KEYS)
- )
- )
-
- # Mark that we're the ones who did it.
- class << CACHE
- def installed_by_interlock; true; end
- end
-
- else
- begin
- CACHE.installed_by_interlock
- rescue NoMethodError
- RAILS_DEFAULT_LOGGER.warn "** interlock: Object::CACHE already defined; will not install a new one"
- # Mark that somebody else installed this CACHE.
- class << CACHE
- def installed_by_interlock; false; end
- end
- end
- end
-
- # Add the fragment cache and lock APIs to the cache singleton. This happens no matter
- # who installed the singleton.
- class << CACHE
- include Interlock::Lock
-
- def read(*args)
- get args.first.to_s
- end
-
- def write(name, content, options = {})
- set(name.to_s,
- content,
- options.is_a?(Hash) ? options[:ttl] : Interlock.config[:ttl] )
- end
- end
- end
-
- #
- # Configure Rails to use the memcached store for fragments, and optionally, sessions.
- #
- def install_fragments
- # Memcached fragment caching is mandatory
- ActionView::Helpers::CacheHelper.class_eval do
- def cache(name = {}, options = nil, &block)
- # Things explode if options does not default to nil
- RAILS_DEFAULT_LOGGER.debug "** fragment #{name} stored via obsolete cache() call"
- @controller.fragment_for(output_buffer, name, options, &block)
- end
- end
- ActionController::Base.cache_store = CACHE
-
- # Sessions are optional
- if Interlock.config[:sessions]
- # XXX Right now this requires memcache-client to be installed, due to a Rails problem.
- # http://dev.rubyonrails.org/ticket/11290
- ActionController::Base.session_store = :mem_cache_store
- ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.update 'cache' => CACHE
- end
- end
-
- #
- # Configure ActiveRecord#find caching.
- #
- def install_finders
- RAILS_DEFAULT_LOGGER.warn "** using interlock finder caches"
- ActiveRecord::Base.send(:include, Interlock::Finders)
- end
-
- end
- end
-end
diff --git a/vendor/plugins/interlock/lib/interlock/core_extensions.rb b/vendor/plugins/interlock/lib/interlock/core_extensions.rb
deleted file mode 100644
index 863085846..000000000
--- a/vendor/plugins/interlock/lib/interlock/core_extensions.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-
-class Object
- def to_interlock_tag
- string = to_s
- string = "empty_string" if string.empty?
- string.escape_tag_fragment
- end
-end
-
-class NilClass
- def to_interlock_tag
- "untagged".escape_tag_fragment
- end
-end
-
-class Hash
- alias :fetch_safely :[]
-
- def value_for_indifferent_key(key)
- fetch_safely(key) or fetch_safely(key.to_s) or fetch_safely(key.to_sym)
- end
-
- alias :v :value_for_indifferent_key
-
- def indifferentiate!
- class << self
- def [](key); value_for_indifferent_key(key); end
- end
- self
- end
-
- def indifferentiate
- self.dup.indifferentiate!
- end
-
- def deep_symbolize_keys!
- symbolize_keys!
- values.each do |value|
- value.deep_symbolize_keys! if value.is_a? Hash
- end
- end
-
- # Compatibility method for Rails 1.2.6. It's also faster.
- unless Hash.instance_methods.include? "slice"
- def slice(*keys)
- hash = {}
- keys.each do |key|
- hash[key] = self[key] if self[key]
- end
- hash
- end
- end
-
-end
-
-class Array
- # Compatibility method for Rails 1.2.6.
- unless Array.instance_methods.include? "extract_options!"
- def extract_options!
- # Method added in Rails rev 7217
- last.is_a?(Hash) ? pop : {}
- end
- end
-end
-
-class String
- def field(i)
- split(":")[i]
- end
-
- def escape_tag_fragment
- gsub(':', '-').gsub(/[^\w\d\-;]/, '_')
- end
-end
diff --git a/vendor/plugins/interlock/lib/interlock/finders.rb b/vendor/plugins/interlock/lib/interlock/finders.rb
deleted file mode 100644
index 4e75238ea..000000000
--- a/vendor/plugins/interlock/lib/interlock/finders.rb
+++ /dev/null
@@ -1,155 +0,0 @@
-
-module Interlock
- module Finders
- def self.included(klass)
- class << klass
- alias_method :find_via_db, :find
- remove_method :find
- end
-
- klass.extend ClassMethods
- end
-
- module ClassMethods
-
- #
- # Cached find.
- #
- # Any other options besides ids short-circuit the cache.
- #
- def find(*args)
- return find_via_db(*args) if args.last.is_a? Hash or args.first.is_a? Symbol
- ids = args.flatten.compact.uniq
- return find_via_db(ids) if ids.blank?
-
- records = find_via_cache(ids, true)
-
- if ids.length > 1 or args.first.is_a?(Array)
- records
- else
- records.first
- end
-
- end
-
- #
- # Cached find_by_id. Short-circuiting works the same as find.
- #
- def find_by_id(*args)
- return method_missing(:find_by_id, *args) if args.last.is_a? Hash
- find_via_cache(args, false).first
- end
-
- #
- # Cached find_all_by_id. Ultrasphinx uses this. Short-circuiting works the same as find.
- #
- def find_all_by_id(*args)
- return method_missing(:find_all_by_id, *args) if args.last.is_a? Hash
- find_via_cache(args, false)
- end
-
- #
- # Build the model cache key for a particular id.
- #
- def caching_key(id)
- Interlock.caching_key(
- self.base_class.name,
- "find",
- id,
- "default"
- )
- end
-
- def finder_ttl
- 0
- end
-
- private
-
- def find_via_cache(ids, should_raise) #:doc:
- results = []
-
- ordered_keys_to_ids = ids.flatten.map { |id| [caching_key(id), id.to_i] }
- keys_to_ids = Hash[*ordered_keys_to_ids.flatten]
-
- records = {}
-
- if ActionController::Base.perform_caching
- load_from_local_cache(records, keys_to_ids)
- load_from_memcached(records, keys_to_ids)
- end
-
- load_from_db(records, keys_to_ids)
-
- # Put them in order
-
- ordered_keys_to_ids.each do |key, |
- record = records[key]
- raise ActiveRecord::RecordNotFound, "Couldn't find #{self.name} with ID=#{keys_to_ids[key]}" if should_raise and !record
- results << record
- end
-
- # Don't return Nil objects, only the found records
- results.compact
- end
-
- def load_from_local_cache(current, keys_to_ids) #:doc:
- # Load from the local cache
- records = {}
- keys_to_ids.each do |key, |
- record = Interlock.local_cache.read(key, nil)
- records[key] = record if record
- end
- current.merge!(records)
- end
-
- def load_from_memcached(current, keys_to_ids) #:doc:
- # Drop to memcached if necessary
- if current.size < keys_to_ids.size
- records = {}
- missed = keys_to_ids.reject { |key, | current[key] }
-
- records = CACHE.get_multi(*missed.keys)
-
- # Set missed to the caches
- records.each do |key, value|
- Interlock.say key, "is loading from memcached", "model"
- Interlock.local_cache.write(key, value, nil)
- end
-
- current.merge!(records)
- end
- end
-
- def load_from_db(current, keys_to_ids) #:doc:
- # Drop to db if necessary
- if current.size < keys_to_ids.size
- missed = keys_to_ids.reject { |key, | current[key] }
- ids_to_keys = keys_to_ids.invert
-
- # Load from the db
- ids_to_find = missed.values
- if ids_to_find.length > 1
- records = send("find_all_by_#{primary_key}".to_sym, ids_to_find, {})
- else
- records = [send("find_by_#{primary_key}".to_sym, ids_to_find.first, {})].compact # explicitly just look for one if that's all that's needed
- end
-
- records = Hash[*(records.map do |record|
- [ids_to_keys[record.id], record]
- end.flatten)]
-
- # Set missed to the caches
- records.each do |key, value|
- Interlock.say key, "is loading from the db", "model"
- Interlock.local_cache.write(key, value, nil)
- CACHE.set key, value, value.class.finder_ttl unless Interlock.config[:disabled]
- end
-
- current.merge!(records)
- end
- end
- end
- end # Finders
-end # Interlock
-
diff --git a/vendor/plugins/interlock/lib/interlock/interlock.rb b/vendor/plugins/interlock/lib/interlock/interlock.rb
deleted file mode 100644
index 29eaa8804..000000000
--- a/vendor/plugins/interlock/lib/interlock/interlock.rb
+++ /dev/null
@@ -1,155 +0,0 @@
-
-module Interlock
-
- class InterlockError < StandardError #:nodoc:
- end
- class DependencyError < InterlockError #:nodoc:
- end
- class ConfigurationError < InterlockError #:nodoc:
- end
- class UsageError < InterlockError #:nodoc:
- end
- class LockAcquisitionError < InterlockError #:nodoc:
- end
- class FragmentConsistencyError < InterlockError #:nodoc:
- end
-
- SCOPE_KEYS = [:controller, :action, :id]
-
- # Buried value extracted from memcache.rb in the memcache-client gem.
- # If one tries to request a key that is too long, the client throws an error.
- # In practice, it seems better to simply avoid ever setting such long keys,
- # so we use this value to achieve such for keys generated by Interlock.
- KEY_LENGTH_LIMIT = 250
-
- # Similarly buried and useful: no whitespace allowed in keys.
- ILLEGAL_KEY_CHARACTERS_PATTERN = /\s/
-
- mattr_accessor :local_cache
-
- # Install the pass-through store. This is used in the console and test
- # environment. In a server environment, the controller callbacks install
- # the memory store before each request.
- @@local_cache = Interlock::PassThroughStore.new
-
- class << self
- #
- # Extract the dependencies from the rest of the arguments and registers
- # them with the appropriate models.
- #
- def extract_options_and_dependencies(dependencies, default = nil)
- options = dependencies.extract_options!
-
- # Hook up the dependencies nested array.
- dependencies.map! { |klass| [klass, :all] }
- options.each do |klass, scope|
- if klass.is_a? Class
- #
- # Beware! Scoping to :id means that a request's params[:id] must equal
- # klass#id or the rule will not trigger. This is because params[:id] is the
- # only record-specific scope include in the key.
- #
- # If you want fancier invalidation, think hard about whether it really
- # matters. Over-invalidation is rarely a problem, but under-invalidation
- # frequently is.
- #
- # "But I need it!" you say. All right, then start using key tags.
- #
- raise Interlock::DependencyError, "#{scope.inspect} is not a valid scope" unless [:all, :id].include?(scope)
- dependencies << [klass, scope.to_sym]
- end
- end
-
- unless dependencies.any?
- # Use the conventional controller/model association if none are provided
- # Can be skipped by calling caching(nil)
- dependencies = [[default, :all]]
- end
-
- # Remove nils
- dependencies.reject! {|klass, scope| klass.nil? }
-
- [options.indifferentiate, dependencies]
- end
-
- #
- # Add each key with scope to the appropriate dependencies array.
- #
- def register_dependencies(dependencies, key)
- return if Interlock.config[:disabled]
-
- Array(dependencies).each do |klass, scope|
- dep_key = dependency_key(klass, scope, key)
-
- # Get the value for this class/key out of the global store.
- this = (CACHE.get(dep_key) || {})[key]
-
- # Make sure to not overwrite broader scopes.
- unless this == :all or this == scope
- # We need to write, so acquire the lock.
- CACHE.lock(dep_key) do |hash|
- Interlock.say key, "registered a dependency on #{klass} -> #{scope.inspect}."
- (hash || {}).merge({key => scope})
- end
- end
- end
- end
-
- def say(key, msg, type = "fragment") #:nodoc:
- log "** #{type} #{key.inspect[1..-2]} #{msg}"
- end
-
- def log(msg)
- case Interlock.config[:log_level]
- when 'debug', 'info', 'warn', 'error'
- log_method = Interlock.config[:log_level]
- else
- log_method = :debug
- end
-
- RAILS_DEFAULT_LOGGER.send( log_method, msg )
- end
-
- #
- # Get the Memcached key for a class's dependency list. We store per-class
- # to reduce lock contention.
- #
- def dependency_key(klass, scope, key)
- id = (scope == :id ? ":#{key.field(4)}" : nil)
- "interlock:#{ENV['RAILS_ASSET_ID']}:dependency:#{klass.name}#{id}"
- end
-
- #
- # Build a fragment key for an explicitly passed context. Shouldn't be called
- # unless you need to write your own fine-grained invalidation rules. Make sure
- # the default ones are really unacceptable before you go to the trouble of
- # rolling your own.
- #
- def caching_key(controller, action, id, tag)
- raise ArgumentError, 'Both controller and action must be specified' unless controller and action
-
- id = (id or 'all').to_interlock_tag
- tag = tag.to_interlock_tag
-
- key = "interlock:#{ENV['RAILS_ASSET_ID']}:#{controller}:#{action}:#{id}:#{tag}"
-
- if key.length > KEY_LENGTH_LIMIT
- old_key = key
- key = key[0..KEY_LENGTH_LIMIT-1]
- say old_key, "truncated to #{key}"
- end
-
- key.gsub ILLEGAL_KEY_CHARACTERS_PATTERN, ''
- end
-
- #
- # Invalidate a particular key.
- #
- def invalidate(key)
- # Console and tests do not install the local cache
- Interlock.local_cache.delete(key) if Interlock.local_cache
- ActionController::Base.cache_store.delete key
- end
-
- end
-end
diff --git a/vendor/plugins/interlock/lib/interlock/lock.rb b/vendor/plugins/interlock/lib/interlock/lock.rb
deleted file mode 100644
index 89479334c..000000000
--- a/vendor/plugins/interlock/lib/interlock/lock.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-
-module Interlock
- module Lock
-
- #
- # Try to acquire a global lock from memcached for a particular key.
- # If successful, yield and set the key to the return value, then release
- # the lock.
- #
- # Based on http://rubyurl.com/Sw7 , which I partially wrote.
- #
-
- def lock(key, lock_expiry = 30, retries = 5)
- retries.times do |count|
-
- # We have to be compatible with both client APIs. Eventually we can use Memcached#cas
- # for this.
- begin
- response = CACHE.add("lock:#{key}", "Locked by #{Process.pid}", lock_expiry)
- # Nil is a successful response for Memcached 0.11, and "STORED\r\n" for MemCache.
- response = [true, nil, "STORED\r\n"].include?(response)
- rescue Memcached::NotStored
- # Do nothing
- end
-
- if response
- begin
- value = yield(CACHE.get(key))
- CACHE.set(key, value)
- return value
- ensure
- CACHE.delete("lock:#{key}")
- end
- else
- # Wait
- sleep((2**count) / 2.0)
- end
- end
-
- raise ::Interlock::LockAcquisitionError, "Couldn't acquire lock for #{key}"
- end
-
- end
-end
diff --git a/vendor/plugins/interlock/lib/interlock/pass_through_store.rb b/vendor/plugins/interlock/lib/interlock/pass_through_store.rb
deleted file mode 100644
index b3926ba01..000000000
--- a/vendor/plugins/interlock/lib/interlock/pass_through_store.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-
-module Interlock
- #
- # A stub class so that does not cache, for use in the test environment and the console
- # when the MemoryStore is not available.
- #
- class PassThroughStore
-
- # Do nothing.
- def nothing(*args)
- nil
- end
-
- alias :read :nothing
- alias :write :nothing
- alias :delete :nothing
-
- end
-end \ No newline at end of file
diff --git a/vendor/plugins/interlock/lib/tasks/interlock.rake b/vendor/plugins/interlock/lib/tasks/interlock.rake
deleted file mode 100644
index a7089f112..000000000
--- a/vendor/plugins/interlock/lib/tasks/interlock.rake
+++ /dev/null
@@ -1,10 +0,0 @@
-
-namespace :interlock do
- desc "Watch the Rails log for Interlock-specific messages"
- task :tail do
- Dir.chdir RAILS_ROOT do
- exec("tail -f log/#{RAILS_ENV}.log | grep interlock")
- end
- end
-end
- \ No newline at end of file