cache.rb 3.4 KB
Newer Older
1 2
require 'benchmark'

3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
module ActiveSupport
  module Cache
    def self.lookup_store(*store_option)
      store, *parameters = *([ store_option ].flatten)

      case store
      when Symbol
        store_class_name = (store == :drb_store ? "DRbStore" : store.to_s.camelize)
        store_class = ActiveSupport::Cache.const_get(store_class_name)
        store_class.new(*parameters)
      when nil
        ActiveSupport::Cache::MemoryStore.new
      else
        store
      end
    end

    def self.expand_cache_key(key, namespace = nil)
      expanded_cache_key = namespace ? "#{namespace}/" : ""
22

23
      if ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]
24
        expanded_cache_key << "#{ENV["RAILS_CACHE_ID"] || ENV["RAILS_APP_VERSION"]}/"
25 26 27
      end

      expanded_cache_key << case
28 29 30 31
        when key.respond_to?(:cache_key)
          key.cache_key
        when key.is_a?(Array)
          key.collect { |element| expand_cache_key(element) }.to_param
J
Jeremy Kemper 已提交
32
        when key
33 34
          key.to_param
        end.to_s
35 36 37 38 39 40 41 42 43

      expanded_cache_key
    end


    class Store
      cattr_accessor :logger

      def threadsafe!
44
        extend ThreadSafety
45 46
      end

47
      # Pass <tt>:force => true</tt> to force a cache miss.
48 49 50
      def fetch(key, options = {})
        @logger_off = true
        if !options[:force] && value = read(key, options)
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
          @logger_off = false
          log("hit", key, options)
          value
        elsif block_given?
          @logger_off = false
          log("miss", key, options)

          value = nil
          seconds = Benchmark.realtime { value = yield }

          @logger_off = true
          write(key, value, options)
          @logger_off = false

          log("write (will save #{'%.5f' % seconds})", key, nil)

          value
        end
      end

      def read(key, options = nil)
        log("read", key, options)
      end

      def write(key, value, options = nil)
        log("write", key, options)
      end

      def delete(key, options = nil)
        log("delete", key, options)
      end

      def delete_matched(matcher, options = nil)
        log("delete matched", matcher.inspect, options)
85 86 87 88 89 90
      end

      def exist?(key, options = nil)
        log("exist?", key, options)
      end

91 92 93 94 95 96 97
      def increment(key, amount = 1)
        log("incrementing", key, amount)
        if num = read(key)
          write(key, num + amount)
        else
          nil
        end
98 99
      end

100 101 102 103 104 105 106 107
      def decrement(key, amount = 1)
        log("decrementing", key, amount)
        if num = read(key)
          write(key, num - amount)
        else
          nil
        end
      end
108

109 110 111 112 113 114 115
      private
        def log(operation, key, options)
          logger.debug("Cache #{operation}: #{key}#{options ? " (#{options.inspect})" : ""}") if logger && !@logger_off
        end
    end

    module ThreadSafety #:nodoc:
116 117
      def self.extended(object) #:nodoc:
        object.instance_variable_set(:@mutex, Mutex.new)
118 119
      end

120 121 122 123 124 125
      %w(read write delete delete_matched exist? increment decrement).each do |method|
        module_eval <<-EOS, __FILE__, __LINE__
          def #{method}(*args)
            @mutex.synchronize { super }
          end
        EOS
126 127 128 129 130 131 132 133 134
      end
    end
  end
end

require 'active_support/cache/file_store'
require 'active_support/cache/memory_store'
require 'active_support/cache/drb_store'
require 'active_support/cache/mem_cache_store'
135
require 'active_support/cache/compressed_mem_cache_store'