Class: SidekiqUniqueJobs::Locksmith

Inherits:
Object
  • Object
show all
Includes:
Connection
Defined in:
lib/sidekiq_unique_jobs/locksmith.rb

Overview

Lock manager class that handles all the various locks

rubocop:disable Metrics/ClassLength

Author:

Instance Method Summary collapse

Methods included from Connection

included, #redis

Constructor Details

#initialize(item, redis_pool = nil) ⇒ Locksmith

Returns a new instance of Locksmith.

Parameters:

  • item (Hash)

    a Sidekiq job hash

  • redis_pool (Sidekiq::RedisConnection, ConnectionPool) (defaults to: nil)

    the redis connection

Options Hash (item):

  • :lock_expiration (Integer)

    the configured expiration

  • :jid (String)

    the sidekiq job id

  • :unique_digest (String)

    the unique digest (See: UniqueArgs#unique_digest)



16
17
18
19
20
21
22
23
24
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 16

def initialize(item, redis_pool = nil)
  # @concurrency   = 1 # removed in a0cff5bc42edbe7190d6ede7e7f845074d2d7af6
  @ttl           = item[LOCK_EXPIRATION_KEY] || item[LOCK_TTL_KEY]
  @jid           = item[JID_KEY]
  @unique_digest = item[UNIQUE_DIGEST_KEY] || item[LOCK_DIGEST_KEY]
  @lock_type     = item[LOCK_KEY] || item[UNIQUE_KEY]
  @lock_type   &&= @lock_type.to_sym
  @redis_pool    = redis_pool
end

Instance Method Details

#deleteObject

Deletes the lock unless it has a ttl set



30
31
32
33
34
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 30

def delete
  return if ttl

  delete!
end

#delete!Object

Deletes the lock regardless of if it has a ttl set



37
38
39
40
41
42
43
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 37

def delete!
  Scripts.call(
    :delete,
    redis_pool,
    keys: [exists_key, grabbed_key, available_key, version_key, UNIQUE_SET, unique_digest],
  )
end

#lock(timeout = nil, &block) ⇒ String Also known as: wait

Create a lock for the item

Parameters:

  • timeout (Integer) (defaults to: nil)

    the number of seconds to wait for a lock.

Returns:

  • (String)

    the Sidekiq job_id (jid)



53
54
55
56
57
58
59
60
61
62
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 53

def lock(timeout = nil, &block)
  Scripts.call(:lock, redis_pool,
               keys: [exists_key, grabbed_key, available_key, UNIQUE_SET, unique_digest],
               argv: [jid, ttl, lock_type])

  grab_token(timeout) do |token|
    touch_grabbed_token(token)
    return_token_or_block_value(token, &block)
  end
end

#locked?(token = nil) ⇒ true, ...

Checks if this instance is considered locked

Parameters:

  • token (String) (defaults to: nil)

    the unique token to check for a lock. nil will default to the jid provided in the initializer

  • token (<type>) (defaults to: nil)

    <description>

Returns:

  • (true, false)
  • (<type>)

    <description>



108
109
110
111
112
113
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 108

def locked?(token = nil)
  token ||= jid

  convert_legacy_lock(token)
  redis(redis_pool) { |conn| conn.hexists(grabbed_key, token) }
end

#unlock(token = nil) ⇒ false, String

Removes the lock keys from Redis if locked by the provided jid/token

Returns:

  • (false)

    unless locked?

  • (String)

    Sidekiq job_id (jid) if successful



71
72
73
74
75
76
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 71

def unlock(token = nil)
  token ||= jid
  return false unless locked?(token)

  unlock!(token)
end

#unlock!(token = nil) ⇒ false, String

Removes the lock keys from Redis

Parameters:

  • token (String) (defaults to: nil)

    the token to unlock (defaults to jid)

Returns:

  • (false)

    unless locked?

  • (String)

    Sidekiq job_id (jid) if successful



86
87
88
89
90
91
92
93
94
95
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 86

def unlock!(token = nil)
  token ||= jid

  Scripts.call(
    :unlock,
    redis_pool,
    keys: [exists_key, grabbed_key, available_key, version_key, UNIQUE_SET, unique_digest],
    argv: [token, ttl, lock_type],
  )
end