class LockAndCacheMsgpack::Action
@private
Constants
- NIL
Attributes
blk[R]
key[R]
options[R]
Public Class Methods
new(key, options, blk)
click to toggle source
# File lib/lock_and_cache_msgpack/action.rb, line 8 def initialize(key, options, blk) raise "need a block" unless blk @key = key @options = options.stringify_keys @blk = blk end
Public Instance Methods
digest()
click to toggle source
# File lib/lock_and_cache_msgpack/action.rb, line 25 def digest @digest ||= key.digest end
expires()
click to toggle source
# File lib/lock_and_cache_msgpack/action.rb, line 15 def expires return @expires if defined?(@expires) @expires = options.has_key?('expires') ? options['expires'].to_f.round : nil end
lock_digest()
click to toggle source
# File lib/lock_and_cache_msgpack/action.rb, line 29 def lock_digest @lock_digest ||= key.lock_digest end
nil_expires()
click to toggle source
# File lib/lock_and_cache_msgpack/action.rb, line 20 def nil_expires return @nil_expires if defined?(@nil_expires) @nil_expires = options.has_key?('nil_expires') ? options['nil_expires'].to_f.round : nil end
perform()
click to toggle source
# File lib/lock_and_cache_msgpack/action.rb, line 37 def perform max_lock_wait = options.fetch 'max_lock_wait', LockAndCacheMsgpack.max_lock_wait heartbeat_expires = options.fetch('heartbeat_expires', LockAndCacheMsgpack.heartbeat_expires).to_f.ceil raise "heartbeat_expires must be >= 2 seconds" unless heartbeat_expires >= 2 heartbeat_frequency = (heartbeat_expires / 2).ceil LockAndCacheMsgpack.logger.debug { "[lock_and_cache] A1 #{key.debug} #{Base64.encode64(digest).strip} #{Digest::SHA1.hexdigest digest}" } if storage.exists(digest) and (existing = storage.get(digest)).is_a?(String) return MessagePack.unpack(existing) end LockAndCacheMsgpack.logger.debug { "[lock_and_cache] B1 #{key.debug} #{Base64.encode64(digest).strip} #{Digest::SHA1.hexdigest digest}" } retval = nil lock_manager = LockAndCacheMsgpack.lock_manager lock_info = nil begin Timeout.timeout(max_lock_wait, TimeoutWaitingForLock) do until lock_info = lock_manager.lock(lock_digest, heartbeat_expires*1000) LockAndCacheMsgpack.logger.debug { "[lock_and_cache] C1 #{key.debug} #{Base64.encode64(digest).strip} #{Digest::SHA1.hexdigest digest}" } sleep rand end end LockAndCacheMsgpack.logger.debug { "[lock_and_cache] D1 #{key.debug} #{Base64.encode64(digest).strip} #{Digest::SHA1.hexdigest digest}" } if storage.exists(digest) and (existing = storage.get(digest)).is_a?(String) LockAndCacheMsgpack.logger.debug { "[lock_and_cache] E1 #{key.debug} #{Base64.encode64(digest).strip} #{Digest::SHA1.hexdigest digest}" } retval = MessagePack.unpack existing end unless retval LockAndCacheMsgpack.logger.debug { "[lock_and_cache] F1 #{key.debug} #{Base64.encode64(digest).strip} #{Digest::SHA1.hexdigest digest}" } done = false begin lock_extender = Thread.new do loop do LockAndCacheMsgpack.logger.debug { "[lock_and_cache] heartbeat1 #{key.debug} #{Base64.encode64(digest).strip} #{Digest::SHA1.hexdigest digest}" } break if done sleep heartbeat_frequency break if done LockAndCacheMsgpack.logger.debug { "[lock_and_cache] heartbeat2 #{key.debug} #{Base64.encode64(digest).strip} #{Digest::SHA1.hexdigest digest}" } lock_manager.lock lock_digest, heartbeat_expires*1000, extend: lock_info end end retval = blk.call retval.nil? ? set_nil : set_non_nil(retval) ensure done = true lock_extender.join if lock_extender.status.nil? end end ensure lock_manager.unlock lock_info if lock_info end retval end
set_nil()
click to toggle source
# File lib/lock_and_cache_msgpack/action.rb, line 90 def set_nil if nil_expires storage.setex digest, nil_expires, NIL elsif expires storage.setex digest, expires, NIL else storage.set digest, NIL end end
set_non_nil(retval)
click to toggle source
# File lib/lock_and_cache_msgpack/action.rb, line 100 def set_non_nil(retval) raise "expected not null #{retval.inspect}" if retval.nil? if expires storage.setex digest, expires, MessagePack.pack(retval) else storage.set digest, MessagePack.pack(retval) end end
storage()
click to toggle source
# File lib/lock_and_cache_msgpack/action.rb, line 33 def storage @storage ||= LockAndCacheMsgpack.storage or raise("must set LockAndCacheMsgpack.storage=[Redis]") end