mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 09:42:07 +08:00
52 lines
885 B
Ruby
52 lines
885 B
Ruby
# Cross-process locking using Redis.
|
|
class DistributedMutex
|
|
attr_accessor :redis
|
|
attr_reader :got_lock
|
|
|
|
def initialize(key, redis=nil)
|
|
@key = key
|
|
@redis = redis || $redis
|
|
@got_lock = false
|
|
end
|
|
|
|
def try_to_get_lock
|
|
if redis.setnx @key, Time.now.to_i + 60
|
|
redis.expire @key, 60
|
|
@got_lock = true
|
|
else
|
|
begin
|
|
redis.watch @key
|
|
time = redis.get @key
|
|
if time && time.to_i < Time.now.to_i
|
|
@got_lock = redis.multi do
|
|
redis.set @key, Time.now.to_i + 60
|
|
end
|
|
end
|
|
ensure
|
|
redis.unwatch
|
|
end
|
|
end
|
|
end
|
|
|
|
def get_lock
|
|
return if @got_lock
|
|
|
|
start = Time.now
|
|
while !@got_lock
|
|
try_to_get_lock
|
|
end
|
|
end
|
|
|
|
def release_lock
|
|
redis.del @key
|
|
@got_lock = false
|
|
end
|
|
|
|
def synchronize
|
|
get_lock
|
|
yield
|
|
ensure
|
|
release_lock
|
|
end
|
|
end
|