class PrefixedCacheStore

A caching store that will expire only the keys saved through it, by using a common prefix for the namespace and the version number that can be ratched up to “unlink” all the related keys. It assumes that the keys are being evicted automatically if they do not get used often.

Constants

RETAIN_PREFIX_FOR_SECONDS
VERSION

Attributes

prefix[R]
store[R]

Public Class Methods

new(store, prefix = 'pfx') click to toggle source
# File lib/prefixed_cache_store.rb, line 22
def initialize(store, prefix = 'pfx')
  @store = store
  @prefix = prefix
end

Public Instance Methods

clear(options=nil) click to toggle source

Bump the version prefix making all keys obsolete.

# File lib/prefixed_cache_store.rb, line 94
def clear(options=nil)
  bump_version! # First bump the version
  @last_prefix = nil # Then make sure the cached version number will not be used
  get_and_set_current_version
end
current_version_number() click to toggle source

Returns the current version that has been set for this store

# File lib/prefixed_cache_store.rb, line 101
def current_version_number
  get_and_set_current_version
end
decrement(name, amount = 1, options=nil) click to toggle source

Decrement a cached value.

# File lib/prefixed_cache_store.rb, line 85
def decrement(name, amount = 1, options=nil)
  if @store.method(:decrement).parameters.length > 2
    @store.decrement(prefix_key(name), amount, options)
  else
    @store.increment(prefix_key(name), amount) # Toss the options
  end
end
delete(name, options=nil) click to toggle source
# File lib/prefixed_cache_store.rb, line 59
def delete(name, options=nil)
  @store.delete(prefix_key(name), options)
end
exist?(name, options=nil) click to toggle source
# File lib/prefixed_cache_store.rb, line 55
def exist?(name, options=nil)
  @store.exist?(prefix_key(name), options)
end
fetch(name, options=nil) { || ... } click to toggle source
# File lib/prefixed_cache_store.rb, line 27
def fetch(name, options=nil)
  if block_given?
    @store.fetch(prefix_key(name), options) { yield }
  else
    @store.fetch(prefix_key(name), options)
  end
end
fetch_multi(*names) { |unprefix_key(prefixed_key)| ... } click to toggle source
# File lib/prefixed_cache_store.rb, line 35
def fetch_multi(*names)
  if !@store.respond_to?(:fetch_multi)
    raise NoMethodError, "#{@store.inspect} does not support fetch_multi()"
  end
  
  options = names.extract_options!
  prefixed_keys = names.map{|e| prefix_key(e) }
  @store.fetch_multi(*prefixed_keys, options) do | prefixed_key |
    yield(unprefix_key(prefixed_key))
  end
end
increment(name, amount = 1, options=nil) click to toggle source

Increment a cached value.

# File lib/prefixed_cache_store.rb, line 76
def increment(name, amount = 1, options=nil)
  if @store.method(:increment).parameters.length > 2
    @store.increment(prefix_key(name), amount, options)
  else
    @store.increment(prefix_key(name), amount) # Toss the options
  end
end
read(name, options=nil) click to toggle source
# File lib/prefixed_cache_store.rb, line 47
def read(name, options=nil)
  @store.read(prefix_key(name), options)
end
read_multi(*names) click to toggle source

Reads multiple keys from the cache using a single call to the servers for all keys. Keys must be Strings.

# File lib/prefixed_cache_store.rb, line 65
def read_multi(*names)
  names.extract_options!
  prefixed_names = names.map{|e| prefix_key(e) }
  result = @store.read_multi(*prefixed_names)
  # Unprefix the keys received
  result.inject({}) do |memo, (prefixed_key, value)|
    memo.merge(unprefix_key(prefixed_key) => value)
  end
end
write(name, value, options=nil) click to toggle source
# File lib/prefixed_cache_store.rb, line 51
def write(name, value, options=nil)
  @store.write(prefix_key(name), value, options)
end

Private Instance Methods

bump_version!() click to toggle source
# File lib/prefixed_cache_store.rb, line 107
def bump_version!
  key = [@prefix, "version"].join('-')
  @store.write(key, @store.read(key).to_i + 1) # Redis does not support increment() with ActiveSupport values
end
get_and_set_current_version() click to toggle source

If the version prefix was last seen not too long ago, reuse it without asking the backend for it over and over. If it wasn't just fetch it as normally

# File lib/prefixed_cache_store.rb, line 114
def get_and_set_current_version
  if @last_prefix && @last_seen && (Time.now.utc - @last_seen) < RETAIN_PREFIX_FOR_SECONDS
    @last_prefix
  else
    @last_seen = Time.now.utc
    @last_prefix = read_and_set_current_version_from_backend
    @last_prefix
  end
end
prefix_key(key) click to toggle source
# File lib/prefixed_cache_store.rb, line 129
def prefix_key(key)
  current_version = get_and_set_current_version
  [@prefix, current_version, expanded_key(key)].join('-')
end
read_and_set_current_version_from_backend() click to toggle source
# File lib/prefixed_cache_store.rb, line 124
def read_and_set_current_version_from_backend
  key = [@prefix, "version"].join('-')
  @store.fetch(key) { 0 }
end
unprefix_key(key) click to toggle source
# File lib/prefixed_cache_store.rb, line 134
def unprefix_key(key)
  @prefix_removal_re ||= /^#{prefix}\-\d+\-/ # Memoize to not parse the regex all the time
  key.gsub(@prefix_removal_re, '')
end