Sha256: fa2ba57bd425805ef91688f07a66de7646d7c9bf41d696539a3bd40f81d9c9cd
Contents?: true
Size: 1.34 KB
Versions: 1
Compression:
Stored size: 1.34 KB
Contents
require 'memcache-lock/version' require 'securerandom' class MemcacheLock class Error < RuntimeError; end DEFAULT_OPTIONS = { :initial_wait => 10e-3, # seconds -- first soft fail will wait for 10ms :expiry => 60, # seconds :retries => 11, # these defaults will retry for a total 41sec max } def initialize(cache) @cache = cache end def synchronize(key, options={}) if acquired?(key) yield else acquire_lock(key, options) begin yield ensure release_lock(key) end end end def acquire_lock(key, options={}) options = DEFAULT_OPTIONS.merge(options) 1.upto(options[:retries]) do |attempt| response = @cache.add("lock/#{key}", uid, options[:expiry]) return if response == "STORED\r\n" break if attempt == options[:retries] Kernel.sleep(2 ** (attempt + rand - 1) * options[:initial_wait]) end raise Error, "Couldn't acquire memcache lock for: #{key}" end def release_lock(key) @cache.delete("lock/#{key}") end private def acquired?(key) @cache.get("lock/#{key}") == uid end private # Globally unique ID for the current thread (or close enough) def uid "#{Socket.gethostname}-#{Process.pid}-#{thread_id}" end def thread_id Thread.current[:thread_uid] ||= SecureRandom.hex(4) end end
Version data entries
1 entries across 1 versions & 1 rubygems
Version | Path |
---|---|
ht-memcache-lock-0.3.0 | lib/memcache-lock.rb |