A lock that does not timeout can lead to a standstill and manual cleanup. Simple solution: redis ‘set ex nx’ and memcached ‘add’.
When indefinite locks happen, getting information on why they happen helps to debug the locking mechanism and see if the processes always fail to unlock.
A softer locking approach to receive feedback when locks expire:
Code
def lock timeout = 30 key = 'lock' now = Time.now.to_i if redis.setnx(key, "#{now}-#{Process.pid}-#{Socket.gethostname}") yield elsif (old = redis.get(key)) && now > old.to_i + timeout logger.error("Releasing expired lock #{old}") redis.delete(key) # next process can get the lock end end
Not 100% safe since the delete could cause multiple processes to get a lock, but depending on your usecase this might be an ok tradeoff.