Class: MasterLock::RedisLock
- Inherits:
-
Object
- Object
- MasterLock::RedisLock
- Defined in:
- lib/master_lock/redis_lock.rb
Overview
RedisLock implements a mutex in Redis according to the strategy documented at redis.io/commands/SET#patterns. The lock has a string identifier and when acquired will be registered to an owner, also identified by a string. Locks have an expiration time, after which they will be released automatically so that unexpected failures do not result in locks getting stuck.
Constant Summary collapse
- DEFAULT_SLEEP_INTERVAL =
0.1
Instance Attribute Summary collapse
-
#key ⇒ String
readonly
The unique identifier for the locked resource.
-
#owner ⇒ String
readonly
The identity of the owner acquiring the lock.
-
#redis ⇒ Redis
readonly
The Redis connection used to manage lock.
-
#ttl ⇒ Fixnum
readonly
The lifetime of the lock in seconds.
Instance Method Summary collapse
-
#acquire(timeout:) ⇒ Boolean
Attempt to acquire the lock.
-
#extend ⇒ Boolean
Extend the expiration time of the lock if still held by this owner.
-
#initialize(redis:, key:, owner:, ttl:, sleep_interval: DEFAULT_SLEEP_INTERVAL) ⇒ RedisLock
constructor
A new instance of RedisLock.
-
#release ⇒ Boolean
Release the lock if still held by this owner.
Constructor Details
#initialize(redis:, key:, owner:, ttl:, sleep_interval: DEFAULT_SLEEP_INTERVAL) ⇒ RedisLock
Returns a new instance of RedisLock.
25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'lib/master_lock/redis_lock.rb', line 25 def initialize( redis:, key:, owner:, ttl:, sleep_interval: DEFAULT_SLEEP_INTERVAL ) @redis = redis @key = key @owner = owner @ttl = ttl @sleep_interval = sleep_interval end |
Instance Attribute Details
#key ⇒ String (readonly)
Returns the unique identifier for the locked resource.
17 18 19 |
# File 'lib/master_lock/redis_lock.rb', line 17 def key @key end |
#owner ⇒ String (readonly)
Returns the identity of the owner acquiring the lock.
20 21 22 |
# File 'lib/master_lock/redis_lock.rb', line 20 def owner @owner end |
#redis ⇒ Redis (readonly)
Returns the Redis connection used to manage lock.
14 15 16 |
# File 'lib/master_lock/redis_lock.rb', line 14 def redis @redis end |
#ttl ⇒ Fixnum (readonly)
Returns the lifetime of the lock in seconds.
23 24 25 |
# File 'lib/master_lock/redis_lock.rb', line 23 def ttl @ttl end |
Instance Method Details
#acquire(timeout:) ⇒ Boolean
Attempt to acquire the lock. If the lock is already held, this will attempt multiple times to acquire the lock until the timeout period is up.
44 45 46 47 48 49 50 51 52 |
# File 'lib/master_lock/redis_lock.rb', line 44 def acquire(timeout:) timeout_time = Time.now + timeout loop do locked = redis.set(redis_key, owner, nx: true, px: ttl_ms) return true if locked return false if Time.now >= timeout_time sleep(@sleep_interval) end end |
#extend ⇒ Boolean
Extend the expiration time of the lock if still held by this owner. If the lock is no longer held by the owner, this method will fail and return false. The lock lifetime is extended by the configured ttl.
59 60 61 62 63 64 65 66 67 |
# File 'lib/master_lock/redis_lock.rb', line 59 def extend result = eval_script( RedisScripts::EXTEND_SCRIPT, RedisScripts::EXTEND_SCRIPT_HASH, keys: [redis_key], argv: [owner, ttl_ms] ) result != 0 end |
#release ⇒ Boolean
Release the lock if still held by this owner. If the lock is no longer held by the owner, this method will fail and return false.
73 74 75 76 77 78 79 80 81 |
# File 'lib/master_lock/redis_lock.rb', line 73 def release result = eval_script( RedisScripts::RELEASE_SCRIPT, RedisScripts::RELEASE_SCRIPT_HASH, keys: [redis_key], argv: [owner] ) result != 0 end |