Class SynCache::Cache
In: lib/syncache.rb
Parent: Object

Methods

[]   []=   delete   fetch_or_add   flush   new  

Constants

DEBUG = false   set to true to report every single cache operation to syslog
LOCK_SLEEP = 0.2   a float number of seconds to sleep when a race condition is detected (actual delay is randomized to avoid live lock situation)

Public Class methods

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

[Source]

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

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

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

Public Instance methods

retrieve value from cache if it‘s still fresh

see also Cache#fetch_or_add

[Source]

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

    entry = get_entry(key)
    entry.sync.synchronize(:SH) do
      entry.value
    end
  end

store new value in cache

see also Cache#fetch_or_add

[Source]

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

    entry = get_entry(key)
    entry.sync.synchronize do
      entry.value = value
    end
    value
  end

remove single value from cache

[Source]

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

    @sync.synchronize do
      @cache.delete(key)
    end
  end

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

[Source]

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

    entry = nil   # scope fix
    entry_locked = false
    until entry_locked do
      @sync.synchronize do
        entry = get_entry(key)
        entry_locked = entry.sync.try_lock   # fixme
      end
      sleep(rand * LOCK_SLEEP) unless entry_locked
    end

    begin
      entry.record_access
      entry.value ||= yield
    ensure
      entry.sync.unlock
    end
  end

remove all values from cache

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

[Source]

# File lib/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

[Validate]