Class: Stoplight::Infrastructure::Redis::DataStore::RecoveryLockStore

Inherits:
Object
  • Object
show all
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

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