mirror of
https://github.com/zammad/zammad
synced 2026-05-24 09:48:36 +00:00
58 lines
1.5 KiB
Ruby
58 lines
1.5 KiB
Ruby
# Copyright (C) 2012-2026 Zammad Foundation, https://zammad-foundation.org/
|
|
|
|
##
|
|
# Redlock implementation for distributed locking.
|
|
#
|
|
# TODO: Replace (and remove) this custom class with the existing redlock
|
|
# gem [0], once we get rid of supported linux distributions that are not
|
|
# providing a redis version 6+.
|
|
#
|
|
# [0] https://github.com/leandromoreira/redlock-rb
|
|
module Redlock
|
|
class Client
|
|
def initialize
|
|
@id = SecureRandom.uuid
|
|
@redis = Zammad::Service::Redis.new
|
|
end
|
|
|
|
def lock(resource, ttl, options = {}, &block)
|
|
return extend_ttl(options[:extend]) if options[:extend]
|
|
return if !@redis.set(resource, @id, nx: true, px: ttl)
|
|
|
|
if block
|
|
begin
|
|
yield block
|
|
ensure
|
|
unlock({ resource: resource, value: @id })
|
|
end
|
|
else
|
|
{ resource: resource, value: @id }
|
|
end
|
|
end
|
|
|
|
def unlock(lock_info)
|
|
value = @redis.get(lock_info[:resource])
|
|
return 0 if value != lock_info[:value]
|
|
|
|
@redis.del(lock_info[:resource])
|
|
end
|
|
|
|
def locked?(resource)
|
|
@redis.exists?(resource)
|
|
end
|
|
|
|
private
|
|
|
|
def extend_ttl(lock_info)
|
|
return 0 if !locked?(lock_info[:resource])
|
|
|
|
value = @redis.get(lock_info[:resource])
|
|
return 0 if value != lock_info[:value]
|
|
|
|
ttl = @redis.pttl(lock_info[:resource])
|
|
return if ttl <= 0 || ttl > lock_info[:validity]
|
|
|
|
@redis.pexpire(lock_info[:resource], lock_info[:validity])
|
|
end
|
|
end
|
|
end
|