Class: Stoplight::Infrastructure::Redis::DataStore::RecoveryLockStore
- Inherits:
-
Object
- Object
- Stoplight::Infrastructure::Redis::DataStore::RecoveryLockStore
- Defined in:
- lib/stoplight/infrastructure/redis/data_store/recovery_lock_store.rb
Overview
Distributed recovery lock using Redis SET NX (set-if-not-exists).
Lock Acquisition:
-
Uses unique UUID token to prevent accidental release of others’ locks
-
Atomic SET with NX flag ensures only one process acquires recovery_lock
-
TTL (px: lock_timeout) auto-releases recovery_lock if process crashes
Lock Release:
-
Lua script ensures only token holder can release (token comparison)
-
Best-effort release; TTL cleanup handles failures
Failure Modes:
-
Lock contention: Returns false, caller should skip probe
-
Redis unavailable: raises an error and let caller decide
-
Crashed holder: raises an error and let caller decide. Lock auto-expires after lock_timeout
-
Release failure: Lock auto-expires after lock_timeout
Instance Method Summary collapse
- #acquire_lock(light_name) ⇒ Object
-
#initialize(redis:, lock_timeout:, scripting:) ⇒ RecoveryLockStore
constructor
A new instance of RecoveryLockStore.
- #release_lock(recovery_lock) ⇒ Object
Constructor Details
#initialize(redis:, lock_timeout:, scripting:) ⇒ RecoveryLockStore
Returns a new instance of RecoveryLockStore.
28 29 30 31 32 |
# File 'lib/stoplight/infrastructure/redis/data_store/recovery_lock_store.rb', line 28 def initialize(redis:, lock_timeout:, scripting:) @redis = redis @lock_timeout = lock_timeout @scripting = scripting end |
Instance Method Details
#acquire_lock(light_name) ⇒ Object
34 35 36 37 38 39 40 41 42 |
# File 'lib/stoplight/infrastructure/redis/data_store/recovery_lock_store.rb', line 34 def acquire_lock(light_name) recovery_lock = RecoveryLockToken.new(light_name:) acquired = !!redis.then do |client| client.set(recovery_lock.lock_key, recovery_lock.token, nx: true, px: lock_timeout) end recovery_lock if acquired end |
#release_lock(recovery_lock) ⇒ Object
44 45 46 47 48 49 |
# File 'lib/stoplight/infrastructure/redis/data_store/recovery_lock_store.rb', line 44 def release_lock(recovery_lock) scripting.call( :release_lock, keys: [recovery_lock.lock_key], args: [recovery_lock.token] ) end |