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

Author:

Instance Method Summary collapse

Methods included from Connection

#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)



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

def initialize(item, redis_pool = nil)
  @concurrency   = 1 # removed in a0cff5bc42edbe7190d6ede7e7f845074d2d7af6
  @expiration    = item[LOCK_EXPIRATION_KEY]
  @jid           = item[JID_KEY]
  @unique_digest = item[UNIQUE_DIGEST_KEY]
  @redis_pool    = redis_pool
end

Instance Method Details

#available_countInteger

The number of available resourced for this lock

Returns:

  • (Integer)

    the number of available resources



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

def available_count
  return concurrency unless exists?

  redis(redis_pool) { |conn| conn.llen(available_key) }
end

#deleteObject

Deletes the lock unless it has an expiration set



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

def delete
  return if expiration
  delete!
end

#delete!Object

Deletes the lock regardless of if it has an expiration set



44
45
46
47
48
49
50
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 44

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

#exists?true, false

Checks if the exists key is created in redis

Returns:

  • (true, false)


25
26
27
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 25

def exists?
  redis(redis_pool) { |conn| conn.exists(exists_key) }
end

#lock(timeout = nil) { ... } ⇒ Object 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. nil means wait indefinitely

Yields:

  • the block to execute if a lock is successful

Returns:

  • the Sidekiq job_id (jid)



57
58
59
60
61
62
63
64
65
66
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 57

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

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

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

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

Returns:

  • (true, false)


96
97
98
99
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 96

def locked?(token = nil)
  token ||= jid
  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



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

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

Returns:

  • (false)

    unless locked?

  • (String)

    Sidekiq job_id (jid) if successful



81
82
83
84
85
86
87
88
89
90
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 81

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, expiration],
  )
end