Samizdat: Co-op Engine

Home | About | Documentation | Developers | Download

SynCache 1.0 (2010-03-14)

SynCache is a thread-safe time-limited cache with flexible replacement policy and ability to wrap generation of expensive cache entries in synchronized blocks. SynCache was used in the Samizdat open publishing engine since 2005, and now it's released as a stand-alone module ready for use in other applications.

Download

Example

  require 'syncache'

  @cache = SynCache::Cache.new

  @cache.fetch_or_add('key:1') do
    # expensive operation
  end

  @cache.flush(/^key:/)

Description

SynCache::Cache stores cached objects in a Hash that is protected by an advanced two-level locking mechanism. Two-level locking ensures that:

When number of cache entries exceeds the size limit, the least recently accessed entries are replaced with new data. This replacement strategy is controlled by the SynCache::CacheEntry class and can be changed by overriding its replacement_index() method.

Cache entries are automatically invalidated when their ttl (time to live) is exceeded. Entries can be explicitly invalidated by flush() method. The method can use === operator to compare cache keys against flush base (so that base can be e.g. a Regexp), and invalidates all entries when invoked without the base parameter.

The flush_delay initialization option allows to limit cache's flush rate. When this option is set, SynCache will make sure that at least this many seconds (it can also be a fraction) pass between two flushes. When extra flushes are requested, invalidation of flushed entries is postponed until earliest time when next flush is allowed.

SynCache DRb Server

SynCache::Cache object can be shared between multiple Ruby processes, even across different computers. All you need is the syncache-drb script shipped with this module. This script will start a daemon that serves a SynCache::Cache object over dRuby protocol, with $SAFE set to 1 for security.

To access a remote cache, you will need to use DRb library:

  require 'drb'

  # connect to the remote cache
  @cache = DRbObject.new_with_uri('druby://localhost:9000')

  # allow remote cache to access local objects from fetch_or_add blocks
  DRb.start_service('druby://localhost:0')