class ActiveSupport::Cache::PorpoiseStore

Constants

SHORT_LIFE_CACHE_SIZE

The maximum number of objects to store in the short life cache.

SHORT_LIFE_CACHE_TIME

The number of seconds items in the short cache are allowed to live.

Attributes

namespace[R]
slc[R]
slt[R]

Public Class Methods

new(options = {}) click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 15
def initialize(options = {})
  @namespace = options.fetch(:namespace, "active-support-cache").to_s
end

Public Instance Methods

cleanup(options = nil) click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 19
def cleanup(options = nil)
  short_mem_reset
  
  Porpoise::KeyValueObject.retry_lock_error(20) do
    Porpoise::KeyValueObject.where(["`key` LIKE ?", "#{@namespace}:%"]).
                             where(["expiration_date IS NOT NULL AND expiration_date < ?", Time.now]).
                             pluck(:key).
                             in_groups_of(150) do |object_keys|
    
      Porpoise::KeyValueObject.where(key: object_keys).delete_all
    end
  end
end
clear(options = nil) click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 33
def clear(options = nil)
  short_mem_reset
  Porpoise::KeyValueObject.retry_lock_error(20) do
    Porpoise::KeyValueObject.where(["`key` LIKE ?", "#{@namespace}:%"]).pluck(:key).in_groups_of(150) do |object_keys|
      Porpoise::KeyValueObject.where(key: object_keys).delete_all
    end
  end
end
decrement(name, amount, options = nil) click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 42
def decrement(name, amount, options = nil)
  Porpoise.with_namespace(@namespace) { 
    v = read(name)
    v = v.to_i - amount.to_i
    write(name, v, options)
  }
end
delete(name, options = nil) click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 50
def delete(name, options = nil)
  Porpoise.with_namespace(@namespace) { 
    short_mem_del(name)
    Porpoise::Key.del(name)
  }
end
delete_matched(matcher, options = nil) click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 57
def delete_matched(matcher, options = nil)
  short_mem_reset
  Porpoise.with_namespace(@namespace) { Porpoise::Key.del_matched(matcher) }
end
exists?(name, options = nil) click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 62
def exists?(name, options = nil)
  Porpoise.with_namespace(@namespace) { Porpoise::Key.exists(name) == 1 }
end
fetch(name, options = nil) { |name| ... } click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 66
def fetch(name, options = nil)
  res = read(name)
  if res.nil? && block_given?
    res = yield(name)
    write(name, res, options)
  end
  return res
end
fetch_multi(*names) { |name| ... } click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 75
def fetch_multi(*names)
  res = read_multi(*names)
  return res unless block_given?

  mres = {}
  res.each do |name, value|
    if value.nil?
      mres[name] = yield(name)
      write(name, mres[name])
    else
      mres[name] = value
    end
  end

  return mres
end
increment(name, amount, options = nil) click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 92
def increment(name, amount, options = nil)
  Porpoise.with_namespace(@namespace) {
    v = read(name)
    v = v.to_i + amount.to_i
    write(name, v, options)
  }
end
read(name, options = nil) click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 100
def read(name, options = nil)
  val = Porpoise.with_namespace(@namespace) {
    short_mem_read(name) { Porpoise::String.get(name) }
  }

  begin
    return val.nil? ? nil : Marshal.load(val)
  rescue TypeError
    return val
  rescue ArgumentError => e
    if e.message =~ /marshal data too short/
      return nil
    else
      raise e
    end
  end
end
read_multi(*names) click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 118
def read_multi(*names)
  result = {}
  names.each do |name|
    val = Porpoise.with_namespace(@namespace) { 
      short_mem_read(name) { Porpoise::String.get(name) }
    }
    begin
      result[name] = (val.nil? ? nil : Marshal.load(val))
    rescue TypeError
      result[name] = val
    rescue ArgumentError => e
      if e.message =~ /marshal data too short/
        return nil
      else
        raise e
      end
    end
  end
  return result
end
write(name, value, options = nil) click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 139
def write(name, value, options = nil)
  options = {} if options.nil?
  Porpoise.with_namespace(@namespace) {
    short_mem_write(name, value, options) {
      Porpoise::String.set(name, Marshal.dump(value), options.fetch(:expires_in, nil))
    }
  }
end

Private Instance Methods

short_mem_del(name) click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 197
def short_mem_del(name)
  @slc ||= {}
  @slt ||= {}
  
  @slc.delete(name)
  @slt.delete(name)
end
short_mem_read(name) { || ... } click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 177
def short_mem_read(name)
  @slc ||= {}
  @slt ||= {}
  v = @slc.fetch(name, nil)
  
  # Remove dead items
  if v && (@slt[name] + SHORT_LIFE_CACHE_TIME) < Time.now.to_i
    @slc.delete(name)
    @slt.delete(name)
    v = nil
  end

  if v.nil? && block_given?
    v = yield
    short_mem_write(name, v) unless v.nil?
  end

  return v
end
short_mem_reset() click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 150
def short_mem_reset
  @slc = {}
  @slt = {}
end
short_mem_write(name, value, options = nil) { || ... } click to toggle source
# File lib/active_support/cache/porpoise_store.rb, line 155
def short_mem_write(name, value, options = nil)
  @slc ||= {}
  @slt ||= {}

  # Do not write the short life cache if an item has an expiration time
  unless options && options.has_key?(:expires_in)
    @slt[name] = Time.now.to_i
    @slc[name] = value

    # Remove the oldest entries when cache gets to big
    if @slt.keys.size >= SHORT_LIFE_CACHE_SIZE
      kk = @slt.sort_by { |k,v| value }.shift(@slt.keys.size - SHORT_LIFE_CACHE_SIZE).map { |kv| kv[0] }
      kk.each do |k|
        @slt.delete(k)
        @slc.delete(k)
      end
    end
  end

  yield if block_given?
end