Skip to content

Instantly share code, notes, and snippets.

@nel
Created September 1, 2011 16:23
Show Gist options
  • Save nel/1186564 to your computer and use it in GitHub Desktop.
Save nel/1186564 to your computer and use it in GitHub Desktop.
Memcache Store with controlled expiration
module ActiveSupport
module Cache
class AtomicMemCacheStore < MemCacheStore
ALREADY_STORED = "STORED\r\n"
cattr_accessor :grace_period
@@grace_period = 3.minutes
def read(key, options = nil)
result = super
if result.present?
timer_key = timer_key(key)
#check whether the cache is expired
if @data.get(timer_key, true).nil?
#optimistic lock to avoid concurrent recalculation
if @data.add(timer_key, '', self.class.grace_period, true) != ALREADY_STORED
#extend current cache key life
@data.set(key, result, self.class.grace_period, options && options[:raw])
#trigger cache recalculation
return handle_expired_read(key,result)
end
#already recalculated or expirated in another process/thread
end
#key not expired
end
result
end
def write(key, value, options = nil)
if expiry = expires_in(options)
#extend write expiration period and reset expiration timer
options[:expires_in] = expiry + self.class.grace_period
end
@data.set(timer_key(key), '', expiry, true)
super
end
protected
#simulate empty cache to trigger synchronous cache recalculation
def handle_expired_read(key,result)
nil
end
private
def timer_key(key)
"tk:#{key}"
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment