Rename ExpiringLock to ExclusiveLease
This commit is contained in:
parent
acd9bc0213
commit
cda0b7e1b1
|
@ -246,7 +246,7 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
def ldap_security_check
|
||||
if current_user && current_user.requires_ldap_check?
|
||||
return unless Gitlab::LDAP::Access.try_lock_user(user)
|
||||
return unless Gitlab::LDAP::Access.try_lock_user(current_user)
|
||||
|
||||
unless Gitlab::LDAP::Access.allowed?(current_user)
|
||||
sign_out current_user
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
require 'securerandom'
|
||||
|
||||
module Gitlab
|
||||
# This class implements an 'exclusive lease'. We call it a 'lease'
|
||||
# because it has a set expiry time. We call it 'exclusive' because only
|
||||
# one caller may obtain a lease for a given key at a time. The
|
||||
# implementation is intended to work across GitLab processes and across
|
||||
# servers. It is a 'cheap' alternative to using SQL queries and updates:
|
||||
# you do not need to change the SQL schema to start using
|
||||
# ExclusiveLease.
|
||||
class ExclusiveLease
|
||||
def initialize(key, timeout)
|
||||
@key, @timeout = key, timeout
|
||||
end
|
||||
|
||||
# Try to obtain the lease. Return true on succes,
|
||||
# false if the lease is already taken.
|
||||
def try_obtain
|
||||
!!redis.set(redis_key, redis_value, nx: true, ex: @timeout)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def redis
|
||||
# Maybe someday we want to use a connection pool...
|
||||
@redis ||= Redis.new(url: Gitlab::RedisConfig.url)
|
||||
end
|
||||
|
||||
def redis_key
|
||||
"gitlab:exclusive_lease:#{@key}"
|
||||
end
|
||||
|
||||
def redis_value
|
||||
@redis_value ||= SecureRandom.hex(10)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,52 +0,0 @@
|
|||
module Gitlab
|
||||
# This class implements a distributed self-expiring lock.
|
||||
#
|
||||
# [2] pry(main)> l = Gitlab::ExpiringLock.new('foobar', 5)
|
||||
# => #<Gitlab::ExpiringLock:0x007ffb9d7cb7f8 @key="foobar", @timeout=5>
|
||||
# [3] pry(main)> l.try_lock
|
||||
# => true
|
||||
# [4] pry(main)> l.try_lock # Only the first try_lock succeeds
|
||||
# => false
|
||||
# [5] pry(main)> l.locked?
|
||||
# => true
|
||||
# [6] pry(main)> sleep 5
|
||||
# => 5
|
||||
# [7] pry(main)> l.locked? # After the timeout the lock is released
|
||||
# => false
|
||||
#
|
||||
class ExpiringLock
|
||||
def initialize(key, timeout)
|
||||
@key, @timeout = key, timeout
|
||||
end
|
||||
|
||||
# Try to obtain the lock. Return true on succes,
|
||||
# false if the lock is already taken.
|
||||
def try_lock
|
||||
# INCR does not change the key TTL
|
||||
if redis.incr(redis_key) == 1
|
||||
# We won the race to insert the key into Redis
|
||||
redis.expire(redis_key, @timeout)
|
||||
true
|
||||
else
|
||||
# Somebody else won the race
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
# Check if somebody somewhere locked this key
|
||||
def locked?
|
||||
!!redis.get(redis_key)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def redis
|
||||
# Maybe someday we want to use a connection pool...
|
||||
@redis ||= Redis.new(url: Gitlab::RedisConfig.url)
|
||||
end
|
||||
|
||||
def redis_key
|
||||
"gitlab:expiring_lock:#{@key}"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -10,7 +10,7 @@ module Gitlab
|
|||
LOCK_TIMEOUT = 600
|
||||
|
||||
def self.try_lock_user(user)
|
||||
Gitlab::ExpiringLock.new("user_ldap_check:#{user.id}", LOCK_TIMEOUT).try_lock
|
||||
Gitlab::ExclusiveLease.new("user_ldap_check:#{user.id}", LOCK_TIMEOUT).try_obtain
|
||||
end
|
||||
|
||||
def self.open(user, &block)
|
||||
|
|
Loading…
Reference in New Issue