class Sinatra::RedisCache::Cache
Public Instance Methods
all_keys(params={with_namespace: true})
click to toggle source
# File lib/sinatra/redis-cache.rb, line 100 def all_keys(params={with_namespace: true}) redis.keys("#{namespace}:*").map{|k| params[:with_namespace] ? k : key_without_namespace(k) } end
del(keys)
click to toggle source
# File lib/sinatra/redis-cache.rb, line 104 def del(keys) debug_log "del #{keys.map{|k| key_without_namespace(k)}}" redis.del(keys) end
do(key, expires=config.default_expires, block)
click to toggle source
# File lib/sinatra/redis-cache.rb, line 32 def do(key, expires=config.default_expires, block) debug_log "do #{key_without_namespace(key)}" if Sinatra::RedisCache::Config.environments.include? Sinatra::Base.settings.environment try = 0 begin redis.watch(key = key_with_namespace(key)) do |watched| object = get(key) unless object.empty? if object['locked'] raise SinatraRedisCacheKeyLocked end object['object'] else lock_key(key, watched, config.lock_timeout) new_object = block.call store(key, new_object, expires) new_object end end rescue SinatraRedisCacheKeyLocked sleeptime = (((try += 1)*50 + rand(100).to_f)/1000) debug_log "key is locked, waiting #{sleeptime}s for retry ##{try}." sleep sleeptime retry rescue SinatraRedisCacheKeyAlreadyLocked sleeptime = (((try += 1)*50 + rand(100).to_f)/1000) debug_log "failed to obtain lock, waiting #{sleeptime}s for retry ##{try}." sleep sleeptime retry end else # Just run the block without cache if we're not in an allowed environment block.call end end
flush()
click to toggle source
# File lib/sinatra/redis-cache.rb, line 109 def flush unless (keys = all_keys).empty? del(keys) end end
get(key)
click to toggle source
# File lib/sinatra/redis-cache.rb, line 68 def get(key) debug_log "get #{key_without_namespace(key)}" unless (hash = redis.hgetall(key_with_namespace(key))).nil? hash.each{|k,v| hash[k]=deserialize(v)} else false end end
properties(key)
click to toggle source
# File lib/sinatra/redis-cache.rb, line 90 def properties(key) unless (string = redis.hget(key_with_namespace(key), 'properties')).nil? deserialize(string) end end
store(key, object, expires=config.default_expires)
click to toggle source
# File lib/sinatra/redis-cache.rb, line 77 def store(key, object, expires=config.default_expires) debug_log "store #{key_without_namespace(key)}" properties = { created_at: Time.now.utc.to_i } redis.watch(key = key_with_namespace(key)) do |watched| watched.multi do |multi| multi.hset(key, 'object', serialize(object)) multi.hset(key, 'properties', serialize(properties)) multi.hdel(key, 'locked') multi.expire(key, expires) end end end
ttl(key)
click to toggle source
# File lib/sinatra/redis-cache.rb, line 96 def ttl(key) redis.ttl(key_with_namespace(key)) end
Private Instance Methods
config()
click to toggle source
# File lib/sinatra/redis-cache.rb, line 117 def config Sinatra::RedisCache::Config end
debug_log(message)
click to toggle source
# File lib/sinatra/redis-cache.rb, line 121 def debug_log(message) if config.logger config.logger.debug("sinatra-redis-cache/#{Process.pid}/#{Thread.current.__id__}") { message } end end
deserialize(string)
click to toggle source
# File lib/sinatra/redis-cache.rb, line 155 def deserialize(string) Marshal.load(string) end
key_with_namespace(key)
click to toggle source
# File lib/sinatra/redis-cache.rb, line 135 def key_with_namespace(key) if key.start_with? namespace key else "#{namespace}:#{key}" end end
key_without_namespace(key)
click to toggle source
# File lib/sinatra/redis-cache.rb, line 143 def key_without_namespace(key) if key.start_with? namespace key.gsub(/^#{namespace}:/,'') else key end end
lock_key(key, redis, timeout=config.lock_timeout)
click to toggle source
# File lib/sinatra/redis-cache.rb, line 159 def lock_key(key, redis, timeout=config.lock_timeout) debug_log "locking #{key_without_namespace(key)} for #{timeout}s" unless redis.multi do |multi| multi.hsetnx(key, 'locked', serialize(true)) multi.expire(key, timeout) end.eql? [true,true] raise SinatraRedisCacheKeyAlreadyLocked end end
namespace()
click to toggle source
# File lib/sinatra/redis-cache.rb, line 131 def namespace config.namespace end
redis()
click to toggle source
# File lib/sinatra/redis-cache.rb, line 127 def redis config.redis_conn end
serialize(object)
click to toggle source
# File lib/sinatra/redis-cache.rb, line 151 def serialize(object) Marshal.dump(object) end