This repository is private.
All pages are served over SSL and all pushing and pulling is done over SSH.
No one may fork, clone, or view it unless they are added as a member.
Every repository with this icon (
) is private.
Every repository with this icon (
This repository is public.
Anyone may fork, clone, or view it.
Every repository with this icon (
) is public.
Every repository with this icon (
| e59de604 » | jeremy | 2008-01-31 | 1 | require 'benchmark' | |
| b1164add » | jeremy | 2009-11-08 | 2 | require 'active_support/core_ext/array/wrap' | |
| 699d2146 » | jeremy | 2009-03-28 | 3 | require 'active_support/core_ext/benchmark' | |
| 4 | require 'active_support/core_ext/exception' | ||||
| 5 | require 'active_support/core_ext/class/attribute_accessors' | ||||
| b540eca5 » | jeremy | 2009-11-01 | 6 | require 'active_support/core_ext/object/to_param' | |
| e59de604 » | jeremy | 2008-01-31 | 7 | ||
| 2a9ad9cc » | dhh | 2008-01-03 | 8 | module ActiveSupport | |
| b047929c » | lifo | 2008-11-01 | 9 | # See ActiveSupport::Cache::Store for documentation. | |
| 2a9ad9cc » | dhh | 2008-01-03 | 10 | module Cache | |
| e44076f2 » | jeremy | 2008-11-23 | 11 | autoload :FileStore, 'active_support/cache/file_store' | |
| 12 | autoload :MemoryStore, 'active_support/cache/memory_store' | ||||
| 13 | autoload :SynchronizedMemoryStore, 'active_support/cache/synchronized_memory_store' | ||||
| 14 | autoload :MemCacheStore, 'active_support/cache/mem_cache_store' | ||||
| 15 | autoload :CompressedMemCacheStore, 'active_support/cache/compressed_mem_cache_store' | ||||
| 16 | |||||
| b08c9688 » | methodmissing | 2009-01-17 | 17 | module Strategy | |
| 18 | autoload :LocalCache, 'active_support/cache/strategy/local_cache' | ||||
| 19 | end | ||||
| 20 | |||||
| b047929c » | lifo | 2008-11-01 | 21 | # Creates a new CacheStore object according to the given options. | |
| 22 | # | ||||
| 23 | # If no arguments are passed to this method, then a new | ||||
| 24 | # ActiveSupport::Cache::MemoryStore object will be returned. | ||||
| 25 | # | ||||
| 26 | # If you pass a Symbol as the first argument, then a corresponding cache | ||||
| 27 | # store class under the ActiveSupport::Cache namespace will be created. | ||||
| 28 | # For example: | ||||
| 29 | # | ||||
| 30 | # ActiveSupport::Cache.lookup_store(:memory_store) | ||||
| 31 | # # => returns a new ActiveSupport::Cache::MemoryStore object | ||||
| 32 | # | ||||
| 595e0333 » | jeremy | 2009-04-17 | 33 | # ActiveSupport::Cache.lookup_store(:mem_cache_store) | |
| 34 | # # => returns a new ActiveSupport::Cache::MemCacheStore object | ||||
| b047929c » | lifo | 2008-11-01 | 35 | # | |
| 36 | # Any additional arguments will be passed to the corresponding cache store | ||||
| 37 | # class's constructor: | ||||
| 38 | # | ||||
| 39 | # ActiveSupport::Cache.lookup_store(:file_store, "/tmp/cache") | ||||
| 40 | # # => same as: ActiveSupport::Cache::FileStore.new("/tmp/cache") | ||||
| 41 | # | ||||
| 42 | # If the first argument is not a Symbol, then it will simply be returned: | ||||
| 43 | # | ||||
| 44 | # ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new) | ||||
| 45 | # # => returns MyOwnCacheStore.new | ||||
| 2a9ad9cc » | dhh | 2008-01-03 | 46 | def self.lookup_store(*store_option) | |
| b1164add » | jeremy | 2009-11-08 | 47 | store, *parameters = *Array.wrap(store_option).flatten | |
| 2a9ad9cc » | dhh | 2008-01-03 | 48 | ||
| 49 | case store | ||||
| 50 | when Symbol | ||||
| 595e0333 » | jeremy | 2009-04-17 | 51 | store_class_name = store.to_s.camelize | |
| 2a9ad9cc » | dhh | 2008-01-03 | 52 | store_class = ActiveSupport::Cache.const_get(store_class_name) | |
| 53 | store_class.new(*parameters) | ||||
| 54 | when nil | ||||
| 55 | ActiveSupport::Cache::MemoryStore.new | ||||
| 56 | else | ||||
| 57 | store | ||||
| 58 | end | ||||
| 59 | end | ||||
| 60 | |||||
| 4bf516e0 » | wycats | 2009-08-10 | 61 | RAILS_CACHE_ID = ENV["RAILS_CACHE_ID"] | |
| 62 | RAILS_APP_VERION = ENV["RAILS_APP_VERION"] | ||||
| 63 | EXPANDED_CACHE = RAILS_CACHE_ID || RAILS_APP_VERION | ||||
| 64 | |||||
| 2a9ad9cc » | dhh | 2008-01-03 | 65 | def self.expand_cache_key(key, namespace = nil) | |
| 66 | expanded_cache_key = namespace ? "#{namespace}/" : "" | ||||
| f47c81ff » | jeremy | 2008-06-20 | 67 | ||
| 4bf516e0 » | wycats | 2009-08-10 | 68 | if EXPANDED_CACHE | |
| 69 | expanded_cache_key << "#{RAILS_CACHE_ID || RAILS_APP_VERION}/" | ||||
| 2a9ad9cc » | dhh | 2008-01-03 | 70 | end | |
| 71 | |||||
| 4bf516e0 » | wycats | 2009-08-10 | 72 | expanded_cache_key << | |
| 73 | if key.respond_to?(:cache_key) | ||||
| 00ba4c0c » | jeremy | 2008-06-20 | 74 | key.cache_key | |
| 4bf516e0 » | wycats | 2009-08-10 | 75 | elsif key.is_a?(Array) | |
| 76 | if key.size > 1 | ||||
| 77 | key.collect { |element| expand_cache_key(element) }.to_param | ||||
| 78 | else | ||||
| 79 | key.first.to_param | ||||
| 80 | end | ||||
| 81 | elsif key | ||||
| 00ba4c0c » | jeremy | 2008-06-20 | 82 | key.to_param | |
| 83 | end.to_s | ||||
| 2a9ad9cc » | dhh | 2008-01-03 | 84 | ||
| 85 | expanded_cache_key | ||||
| 86 | end | ||||
| 87 | |||||
| b047929c » | lifo | 2008-11-01 | 88 | # An abstract cache store class. There are multiple cache store | |
| 89 | # implementations, each having its own additional features. See the classes | ||||
| 90 | # under the ActiveSupport::Cache module, e.g. | ||||
| 91 | # ActiveSupport::Cache::MemCacheStore. MemCacheStore is currently the most | ||||
| 92 | # popular cache store for large production websites. | ||||
| 93 | # | ||||
| 94 | # ActiveSupport::Cache::Store is meant for caching strings. Some cache | ||||
| 95 | # store implementations, like MemoryStore, are able to cache arbitrary | ||||
| 96 | # Ruby objects, but don't count on every cache store to be able to do that. | ||||
| 97 | # | ||||
| 98 | # cache = ActiveSupport::Cache::MemoryStore.new | ||||
| 99 | # | ||||
| 100 | # cache.read("city") # => nil | ||||
| 101 | # cache.write("city", "Duckburgh") | ||||
| 102 | # cache.read("city") # => "Duckburgh" | ||||
| 2a9ad9cc » | dhh | 2008-01-03 | 103 | class Store | |
| 8f59d7a8 » | josevalim | 2009-10-09 | 104 | cattr_accessor :logger, :instance_writter => false | |
| 2a9ad9cc » | dhh | 2008-01-03 | 105 | ||
| 4215e9ab » | josevalim | 2009-09-20 | 106 | attr_reader :silence | |
| 107 | alias :silence? :silence | ||||
| ee7d4c47 » | carlhuda | 2009-07-01 | 108 | ||
| 0eef4e55 » | josh | 2008-07-17 | 109 | def silence! | |
| 110 | @silence = true | ||||
| 111 | self | ||||
| 112 | end | ||||
| 113 | |||||
| 987d5011 » | lifo | 2009-10-09 | 114 | def mute | |
| 115 | previous_silence, @silence = defined?(@silence) && @silence, true | ||||
| 116 | yield | ||||
| 117 | ensure | ||||
| 118 | @silence = previous_silence | ||||
| 119 | end | ||||
| 120 | |||||
| 8f59d7a8 » | josevalim | 2009-10-09 | 121 | # Set to true if cache stores should be instrumented. By default is false. | |
| 122 | def self.instrument=(boolean) | ||||
| 123 | Thread.current[:instrument_cache_store] = boolean | ||||
| 124 | end | ||||
| 125 | |||||
| 126 | def self.instrument | ||||
| 127 | Thread.current[:instrument_cache_store] || false | ||||
| 128 | end | ||||
| 129 | |||||
| b047929c » | lifo | 2008-11-01 | 130 | # Fetches data from the cache, using the given key. If there is data in | |
| 131 | # the cache with the given key, then that data is returned. | ||||
| 132 | # | ||||
| 133 | # If there is no such data in the cache (a cache miss occurred), then | ||||
| 134 | # then nil will be returned. However, if a block has been passed, then | ||||
| 135 | # that block will be run in the event of a cache miss. The return value | ||||
| 136 | # of the block will be written to the cache under the given cache key, | ||||
| 137 | # and that return value will be returned. | ||||
| 138 | # | ||||
| 139 | # cache.write("today", "Monday") | ||||
| 140 | # cache.fetch("today") # => "Monday" | ||||
| 141 | # | ||||
| 142 | # cache.fetch("city") # => nil | ||||
| 143 | # cache.fetch("city") do | ||||
| 144 | # "Duckburgh" | ||||
| 145 | # end | ||||
| 146 | # cache.fetch("city") # => "Duckburgh" | ||||
| 147 | # | ||||
| 148 | # You may also specify additional options via the +options+ argument. | ||||
| 149 | # Setting <tt>:force => true</tt> will force a cache miss: | ||||
| 150 | # | ||||
| 151 | # cache.write("today", "Monday") | ||||
| 152 | # cache.fetch("today", :force => true) # => nil | ||||
| 153 | # | ||||
| 154 | # Other options will be handled by the specific cache store implementation. | ||||
| 155 | # Internally, #fetch calls #read, and calls #write on a cache miss. | ||||
| 156 | # +options+ will be passed to the #read and #write calls. | ||||
| 157 | # | ||||
| 158 | # For example, MemCacheStore's #write method supports the +:expires_in+ | ||||
| 159 | # option, which tells the memcached server to automatically expire the | ||||
| b5775c2b » | lifo | 2009-06-21 | 160 | # cache item after a certain period. This options is also supported by | |
| 161 | # FileStore's #read method. We can use this option with #fetch too: | ||||
| b047929c » | lifo | 2008-11-01 | 162 | # | |
| 163 | # cache = ActiveSupport::Cache::MemCacheStore.new | ||||
| 164 | # cache.fetch("foo", :force => true, :expires_in => 5.seconds) do | ||||
| 165 | # "bar" | ||||
| 166 | # end | ||||
| 167 | # cache.fetch("foo") # => "bar" | ||||
| 168 | # sleep(6) | ||||
| 169 | # cache.fetch("foo") # => nil | ||||
| 4215e9ab » | josevalim | 2009-09-20 | 170 | def fetch(key, options = {}, &block) | |
| 2f7ce08b » | jeremy | 2008-01-31 | 171 | if !options[:force] && value = read(key, options) | |
| 2a9ad9cc » | dhh | 2008-01-03 | 172 | value | |
| 173 | elsif block_given? | ||||
| 4215e9ab » | josevalim | 2009-09-20 | 174 | result = instrument(:generate, key, options, &block) | |
| 175 | write(key, result, options) | ||||
| 176 | result | ||||
| 2a9ad9cc » | dhh | 2008-01-03 | 177 | end | |
| 178 | end | ||||
| 179 | |||||
| b047929c » | lifo | 2008-11-01 | 180 | # Fetches data from the cache, using the given key. If there is data in | |
| 181 | # the cache with the given key, then that data is returned. Otherwise, | ||||
| 182 | # nil is returned. | ||||
| 183 | # | ||||
| 184 | # You may also specify additional options via the +options+ argument. | ||||
| 185 | # The specific cache store implementation will decide what to do with | ||||
| 186 | # +options+. | ||||
| b5775c2b » | lifo | 2009-06-21 | 187 | # | |
| 188 | # For example, FileStore supports the +:expires_in+ option, which | ||||
| 189 | # makes the method return nil for cache items older than the specified | ||||
| 190 | # period. | ||||
| 4215e9ab » | josevalim | 2009-09-20 | 191 | def read(key, options = nil, &block) | |
| 192 | instrument(:read, key, options, &block) | ||||
| 2a9ad9cc » | dhh | 2008-01-03 | 193 | end | |
| 194 | |||||
| b047929c » | lifo | 2008-11-01 | 195 | # Writes the given value to the cache, with the given key. | |
| 196 | # | ||||
| 197 | # You may also specify additional options via the +options+ argument. | ||||
| 198 | # The specific cache store implementation will decide what to do with | ||||
| 199 | # +options+. | ||||
| 200 | # | ||||
| 201 | # For example, MemCacheStore supports the +:expires_in+ option, which | ||||
| 202 | # tells the memcached server to automatically expire the cache item after | ||||
| 203 | # a certain period: | ||||
| 204 | # | ||||
| 205 | # cache = ActiveSupport::Cache::MemCacheStore.new | ||||
| 206 | # cache.write("foo", "bar", :expires_in => 5.seconds) | ||||
| 207 | # cache.read("foo") # => "bar" | ||||
| 208 | # sleep(6) | ||||
| 209 | # cache.read("foo") # => nil | ||||
| 4215e9ab » | josevalim | 2009-09-20 | 210 | def write(key, value, options = nil, &block) | |
| 211 | instrument(:write, key, options, &block) | ||||
| 2a9ad9cc » | dhh | 2008-01-03 | 212 | end | |
| 213 | |||||
| 4215e9ab » | josevalim | 2009-09-20 | 214 | def delete(key, options = nil, &block) | |
| 215 | instrument(:delete, key, options, &block) | ||||
| 2a9ad9cc » | dhh | 2008-01-03 | 216 | end | |
| 217 | |||||
| 4215e9ab » | josevalim | 2009-09-20 | 218 | def delete_matched(matcher, options = nil, &block) | |
| 219 | instrument(:delete_matched, matcher.inspect, options, &block) | ||||
| 99860b72 » | josevalim | 2008-05-16 | 220 | end | |
| 221 | |||||
| 4215e9ab » | josevalim | 2009-09-20 | 222 | def exist?(key, options = nil, &block) | |
| 223 | instrument(:exist?, key, options, &block) | ||||
| 99860b72 » | josevalim | 2008-05-16 | 224 | end | |
| 225 | |||||
| fef82759 » | tobi | 2008-04-29 | 226 | def increment(key, amount = 1) | |
| 227 | if num = read(key) | ||||
| 228 | write(key, num + amount) | ||||
| 229 | else | ||||
| 230 | nil | ||||
| 231 | end | ||||
| 2a9ad9cc » | dhh | 2008-01-03 | 232 | end | |
| 233 | |||||
| fef82759 » | tobi | 2008-04-29 | 234 | def decrement(key, amount = 1) | |
| 235 | if num = read(key) | ||||
| 236 | write(key, num - amount) | ||||
| 237 | else | ||||
| 238 | nil | ||||
| 239 | end | ||||
| 240 | end | ||||
| 94cf6675 » | josh | 2008-07-17 | 241 | ||
| 2a9ad9cc » | dhh | 2008-01-03 | 242 | private | |
| b5775c2b » | lifo | 2009-06-21 | 243 | def expires_in(options) | |
| ee7d4c47 » | carlhuda | 2009-07-01 | 244 | expires_in = options && options[:expires_in] | |
| 245 | raise ":expires_in must be a number" if expires_in && !expires_in.is_a?(Numeric) | ||||
| 246 | expires_in || 0 | ||||
| b5775c2b » | lifo | 2009-06-21 | 247 | end | |
| 248 | |||||
| 4215e9ab » | josevalim | 2009-09-20 | 249 | def instrument(operation, key, options, &block) | |
| 8f59d7a8 » | josevalim | 2009-10-09 | 250 | log(operation, key, options) | |
| 4215e9ab » | josevalim | 2009-09-20 | 251 | ||
| 8f59d7a8 » | josevalim | 2009-10-09 | 252 | if self.class.instrument | |
| 253 | payload = { :key => key } | ||||
| 254 | payload.merge!(options) if options.is_a?(Hash) | ||||
| 2d7abe24 » | josevalim | 2009-10-15 | 255 | ActiveSupport::Notifications.instrument(:"cache_#{operation}", payload, &block) | |
| 8f59d7a8 » | josevalim | 2009-10-09 | 256 | else | |
| 257 | yield | ||||
| 258 | end | ||||
| 4215e9ab » | josevalim | 2009-09-20 | 259 | end | |
| 260 | |||||
| 2a9ad9cc » | dhh | 2008-01-03 | 261 | def log(operation, key, options) | |
| af0d1fa8 » | josevalim | 2009-10-07 | 262 | return unless logger && !silence? | |
| 263 | logger.debug("Cache #{operation}: #{key}#{options ? " (#{options.inspect})" : ""}") | ||||
| 2a9ad9cc » | dhh | 2008-01-03 | 264 | end | |
| 265 | end | ||||
| 266 | end | ||||
| 267 | end | ||||








