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

Inherits:
Object
  • Object
show all
Defined in:
lib/stoplight/infrastructure/redis/data_store/recovery_lock_store.rb,
sig/_private/stoplight/infrastructure/redis/data_store/recovery_lock_store.rbs

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 Attribute Summary collapse

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 Attribute Details

#lock_timeoutInteger (readonly)

Returns the value of attribute lock_timeout.

Returns:

  • (Integer)


54
55
56
# File 'lib/stoplight/infrastructure/redis/data_store/recovery_lock_store.rb', line 54

def lock_timeout
  @lock_timeout
end

#redisredis (readonly)

Returns the value of attribute redis.

Returns:



53
54
55
# File 'lib/stoplight/infrastructure/redis/data_store/recovery_lock_store.rb', line 53

def redis
  @redis
end

#scriptingScripting (readonly)

Returns the value of attribute scripting.

Returns:



55
56
57
# File 'lib/stoplight/infrastructure/redis/data_store/recovery_lock_store.rb', line 55

def scripting
  @scripting
end

Instance Method Details

#acquire_lock(light_name) ⇒ RecoveryLockToken?

Parameters:

  • light_name (String)

Returns:



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) ⇒ void

This method returns an undefined value.

Parameters:



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