class ActiveSupport::Cache::DalliStore
Constants
- ESCAPE_KEY_CHARS
Attributes
Public Class Methods
Creates a new DalliStore
object, with the given memcached server addresses. Each address is either a host name, or a host-with-port string in the form of “host_name:port”. For example:
ActiveSupport::Cache::DalliStore.new("localhost", "server-downstairs.localnetwork:8229")
If no addresses are specified, then DalliStore
will connect to localhost port 11211 (the default memcached port).
Connection Pool support
If you are using multithreaded Rails, the Rails.cache singleton can become a source of contention. You can use a connection pool of Dalli
clients with Rails.cache by passing :pool_size and/or :pool_timeout:
config.cache_store = :dalli_store, 'localhost:11211', :pool_size => 10
Both pool options default to 5. You must include the `connection_pool` gem if you wish to use pool support.
# File lib/active_support/cache/dalli_store.rb, line 47 def initialize(*addresses) addresses = addresses.flatten options = addresses.extract_options! @options = options.dup pool_options = {} pool_options[:size] = options[:pool_size] if options[:pool_size] pool_options[:timeout] = options[:pool_timeout] if options[:pool_timeout] @options[:compress] ||= @options[:compression] addresses.compact! servers = if addresses.empty? nil # use the default from Dalli::Client else addresses end if pool_options.empty? @data = Dalli::Client.new(servers, @options) else @data = ::ConnectionPool.new(pool_options) { Dalli::Client.new(servers, @options.merge(:threadsafe => false)) } end extend Strategy::LocalCache extend LocalCacheEntryUnwrapAndRaw end
Public Instance Methods
Clear any local cache
# File lib/active_support/cache/dalli_store.rb, line 274 def cleanup(options=nil) end
Clear the entire cache on all memcached servers. This method should be used with care when using a shared cache.
# File lib/active_support/cache/dalli_store.rb, line 263 def clear(options=nil) instrument(:clear, 'flushing all keys') do with { |c| c.flush_all } end rescue Dalli::DalliError => e logger.error("DalliError: #{e.message}") if logger raise if raise_errors? nil end
Access the underlying Dalli::Client
or ConnectionPool instance for access to get_multi, etc.
# File lib/active_support/cache/dalli_store.rb, line 77 def dalli @data end
Decrement a cached value. This method uses the memcached decr atomic operator and can only be used on values written with the :raw option. Calling it on a value not stored with :raw will fail. :initial defaults to zero, as if the counter was initially zero. memcached counters cannot hold negative values.
# File lib/active_support/cache/dalli_store.rb, line 247 def decrement(name, amount = 1, options=nil) options ||= {} name = namespaced_key(name, options) initial = options.has_key?(:initial) ? options[:initial] : 0 expires_in = options[:expires_in] instrument(:decrement, name, :amount => amount) do with { |c| c.decr(name, amount, expires_in, initial) } end rescue Dalli::DalliError => e logger.error("DalliError: #{e.message}") if logger raise if raise_errors? nil end
# File lib/active_support/cache/dalli_store.rb, line 157 def delete(name, options=nil) options ||= {} name = namespaced_key(name, options) instrument(:delete, name, options) do |payload| delete_entry(name, options) end end
# File lib/active_support/cache/dalli_store.rb, line 149 def exist?(name, options=nil) options ||= {} name = namespaced_key(name, options) log(:exist, name, options) !read_entry(name, options).nil? end
Fetch the value associated with the key. If a value is found, then it is returned.
If a value is not found and no block is given, then nil is returned.
If a value is not found (or if the found value is nil and :cache_nils is false) and a block is given, the block will be invoked and its return value written to the cache and returned.
# File lib/active_support/cache/dalli_store.rb, line 93 def fetch(name, options=nil) options ||= {} options[:cache_nils] = true if @options[:cache_nils] namespaced_name = namespaced_key(name, options) not_found = options[:cache_nils] ? Dalli::Server::NOT_FOUND : nil if block_given? entry = not_found unless options[:force] entry = instrument(:read, namespaced_name, options) do |payload| read_entry(namespaced_name, options).tap do |result| if payload payload[:super_operation] = :fetch payload[:hit] = result != not_found end end end end if entry == not_found result = instrument(:generate, namespaced_name, options) do |payload| yield end write(name, result, options) result else instrument(:fetch_hit, namespaced_name, options) { |payload| } entry end else read(name, options) end end
Fetches data from the cache, using the given keys. If there is data in the cache with the given keys, then that data is returned. Otherwise, the supplied block is called for each key for which there was no data, and the result will be written to the cache and returned.
# File lib/active_support/cache/dalli_store.rb, line 198 def fetch_multi(*names) options = names.extract_options! mapping = names.inject({}) { |memo, name| memo[namespaced_key(name, options)] = name; memo } instrument(:fetch_multi, mapping.keys) do with do |connection| results = connection.get_multi(mapping.keys) connection.multi do mapping.inject({}) do |memo, (expanded, name)| memo[name] = results[expanded] if memo[name].nil? value = yield(name) memo[name] = value options = options.merge(:connection => connection) write_entry(expanded, value, options) end memo end end end end end
Increment a cached value. This method uses the memcached incr atomic operator and can only be used on values written with the :raw option. Calling it on a value not stored with :raw will fail. :initial defaults to the amount passed in, as if the counter was initially zero. memcached counters cannot hold negative values.
# File lib/active_support/cache/dalli_store.rb, line 228 def increment(name, amount = 1, options=nil) options ||= {} name = namespaced_key(name, options) initial = options.has_key?(:initial) ? options[:initial] : amount expires_in = options[:expires_in] instrument(:increment, name, :amount => amount) do with { |c| c.incr(name, amount, expires_in, initial) } end rescue Dalli::DalliError => e logger.error("DalliError: #{e.message}") if logger raise if raise_errors? nil end
# File lib/active_support/cache/dalli_store.rb, line 286 def logger Dalli.logger end
# File lib/active_support/cache/dalli_store.rb, line 290 def logger=(new_logger) Dalli.logger = new_logger end
Silence the logger within a block.
# File lib/active_support/cache/dalli_store.rb, line 18 def mute previous_silence, @silence = defined?(@silence) && @silence, true yield ensure @silence = previous_silence end
# File lib/active_support/cache/dalli_store.rb, line 126 def read(name, options=nil) options ||= {} name = namespaced_key(name, options) instrument(:read, name, options) do |payload| entry = read_entry(name, options) payload[:hit] = !entry.nil? if payload entry end end
Reads multiple keys from the cache using a single call to the servers for all keys. Keys must be Strings.
# File lib/active_support/cache/dalli_store.rb, line 168 def read_multi(*names) options = names.extract_options! mapping = names.inject({}) { |memo, name| memo[namespaced_key(name, options)] = name; memo } instrument(:read_multi, mapping.keys) do results = {} if local_cache mapping.each_key do |key| if value = local_cache.read_entry(key, options) results[key] = value end end end data = with { |c| c.get_multi(mapping.keys - results.keys) } results.merge!(data) results.inject({}) do |memo, (inner, _)| entry = results[inner] # NB Backwards data compatibility, to be removed at some point value = (entry.is_a?(ActiveSupport::Cache::Entry) ? entry.value : entry) memo[mapping[inner]] = value local_cache.write_entry(inner, value, options) if local_cache memo end end end
# File lib/active_support/cache/dalli_store.rb, line 282 def reset with { |c| c.reset } end
Silence the logger.
# File lib/active_support/cache/dalli_store.rb, line 12 def silence! @silence = true self end
Get the statistics from the memcached servers.
# File lib/active_support/cache/dalli_store.rb, line 278 def stats with { |c| c.stats } end
# File lib/active_support/cache/dalli_store.rb, line 81 def with(&block) @data.with(&block) end
# File lib/active_support/cache/dalli_store.rb, line 137 def write(name, value, options=nil) options ||= {} name = namespaced_key(name, options) instrument(:write, name, options) do |payload| with do |connection| options = options.merge(:connection => connection) write_entry(name, value, options) end end end
Private Instance Methods
# File lib/active_support/cache/dalli_store.rb, line 366 def instrument(operation, key, options=nil) log(operation, key, options) payload = { :key => key } payload.merge!(options) if options.is_a?(Hash) ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload){ yield(payload) } end
# File lib/active_support/cache/dalli_store.rb, line 374 def log(operation, key, options=nil) return unless logger && logger.debug? && !silence? logger.debug("Cache #{operation}: #{key}#{options.blank? ? "" : " (#{options.inspect})"}") end
# File lib/active_support/cache/dalli_store.rb, line 332 def namespaced_key(key, options) key = expanded_key(key) namespace = options[:namespace] if options prefix = namespace.is_a?(Proc) ? namespace.call : namespace key = "#{prefix}:#{key}" if prefix key end
# File lib/active_support/cache/dalli_store.rb, line 379 def raise_errors? !!@options[:raise_errors] end