class SynCache::Cache

Constants

LOCK_SLEEP

a float number of seconds to sleep when a race condition is detected (actual delay is randomized to avoid live lock situation)

Attributes

debug[RW]

set to true to report every single cache operation

Public Class Methods

new(ttl = 60*60, max_size = 5000, flush_delay = nil) click to toggle source

ttl (time to live) is time in seconds from the last access until cache entry is expired (set to nil to disable time limit)

max_size is max number of objects in cache

flush_delay is used to rate-limit flush operations: if less than that number of seconds has passed since last flush, next flush will be delayed; default is no rate limit

# File lib/syncache/syncache.rb, line 80
def initialize(ttl = 60*60, max_size = 5000, flush_delay = nil)
  @ttl = ttl
  @max_size = max_size
  @debug = false

  if @flush_delay = flush_delay
    @last_flush = Time.now
  end

  @sync = Mutex.new
  @cache = {}
end

Public Instance Methods

[](key) click to toggle source

retrieve value from cache if it's still fresh

see also #fetch_or_add

# File lib/syncache/syncache.rb, line 152
def [](key)
  debug { '[] ' << key.to_s }

  entry = get_locked_entry(key, false)
  unless entry.nil?
    begin
      return entry.value
    ensure
      entry.sync.unlock
    end
  end
end
[]=(key, value) click to toggle source

store new value in cache

see also #fetch_or_add

# File lib/syncache/syncache.rb, line 137
def []=(key, value)
  debug { '[]= ' << key.to_s }

  entry = get_locked_entry(key)
  begin
    return entry.value = value
  ensure
    entry.sync.unlock
  end
end
delete(key) click to toggle source

remove single value from cache

# File lib/syncache/syncache.rb, line 125
def delete(key)
  debug { 'delete ' << key.to_s }

  @sync.synchronize do
    @cache.delete(key)
  end
end
fetch_or_add(key) { || ... } click to toggle source

initialize missing cache entry from supplied block

this is the preferred method of adding values to the cache as it locks the key for the duration of computation of the supplied block to prevent parallel execution of resource-intensive actions

# File lib/syncache/syncache.rb, line 171
def fetch_or_add(key)
  debug { 'fetch_or_add ' << key.to_s }

  entry = get_locked_entry(key)
  begin
    if entry.value.nil?
      entry.value = yield
    end
    return entry.value
  ensure
    entry.sync.unlock
  end
end
flush(base = nil) click to toggle source

remove all values from cache

if base is given, only values with keys matching the base (using === operator) are removed

# File lib/syncache/syncache.rb, line 102
def flush(base = nil)
  debug { 'flush ' << base.to_s }

  @sync.synchronize do

    if @flush_delay
      next_flush = @last_flush + @flush_delay

      if next_flush > Time.now
        flush_at(next_flush, base)
      else
        flush_now(base)
        @last_flush = Time.now
      end

    else
      flush_now(base)
    end
  end
end