Class: SidekiqUniqueJobs::Locksmith

Inherits:
Object
  • Object
show all
Includes:
Connection, JSON, Logging, Reflectable, Script::Caller, Timing
Defined in:
lib/sidekiq_unique_jobs/locksmith.rb

Overview

Lock manager class that handles all the various locks

Author:

  • Mikael Henriksson <mikael@mhenrixon.com>

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from JSON

dump_json, load_json, safe_load_json

Methods included from Script::Caller

call_script, debug_lua, do_call, extract_args, max_history, normalize_argv, now_f, redis_version

Methods included from Timing

clock_stamp, now_f, time_source, timed

Methods included from Reflectable

#reflect

Methods included from Logging

#build_message, included, #log_debug, #log_error, #log_fatal, #log_info, #log_warn, #logger, #logging_context, #with_configured_loggers_context, #with_logging_context

Methods included from Connection

included, #redis

Constructor Details

#initialize(item, redis_pool = nil) ⇒ Locksmith

Initialize a new Locksmith instance

Parameters:

  • item (Hash)

    a Sidekiq job hash

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

    the redis connection



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

def initialize(item, redis_pool = nil)
  @item        = item
  @key         = Key.new(item[LOCK_DIGEST] || item[UNIQUE_DIGEST])
  @job_id      = item[JID]
  @config      = LockConfig.new(item)
  @redis_pool  = redis_pool
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



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

def config
  @config
end

#itemObject (readonly)

Returns the value of attribute item.



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

def item
  @item
end

#job_idObject (readonly)

Returns the value of attribute job_id.



22
23
24
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 22

def job_id
  @job_id
end

#keyObject (readonly)

Returns the value of attribute key.



18
19
20
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 18

def key
  @key
end

Instance Method Details

#==(other) ⇒ Object



130
131
132
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 130

def ==(other)
  key == other.key && job_id == other.job_id
end

#deleteObject

Deletes the lock unless it has a pttl set



101
102
103
104
105
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 101

def delete
  return if config.pttl.positive?

  delete!
end

#delete!Object

Deletes the lock regardless of if it has a pttl set



93
94
95
96
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 93

def delete!
  # Force unlock regardless of lock_type (pass "force" to skip until_expired check)
  call_script(:unlock, key.to_a, [job_id, "force"])
end

#execute { ... } ⇒ Object?

Execute a block with the lock held

Yields:

  • the block to execute

Returns:

  • (Object, nil)

    the block’s return value if locked, nil if not

Raises:



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

def execute(&block)
  raise SidekiqUniqueJobs::InvalidArgument, "#execute needs a block" unless block

  locked_jid = lock
  return unless locked_jid

  yield
end

#inspectObject



126
127
128
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 126

def inspect
  to_s
end

#lock(wait: nil) ⇒ String?

Acquire the lock for this job

Parameters:

Returns:

  • (String, nil)

    the job_id if locked, nil if not



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

def lock(wait: nil) # rubocop:disable Lint/UnusedMethodArgument
  result = call_script(:lock, key.to_a, lock_argv)
  return unless result

  reflect(:debug, :locked, item, result)
  job_id
end

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

Checks if this instance is considered locked

Parameters:

  • conn (Redis, nil) (defaults to: nil)

    optional redis connection

Returns:

  • (true, false)


114
115
116
117
118
119
120
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 114

def locked?(conn = nil)
  if conn
    taken?(conn)
  else
    redis(redis_pool) { |rcon| taken?(rcon) }
  end
end

#to_sObject



122
123
124
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 122

def to_s
  "Locksmith##{object_id}(digest=#{key} job_id=#{job_id} locked=#{locked?})"
end

#unlock(conn = nil) ⇒ String?

Release the lock for this job

Returns:

  • (String, nil)

    the job_id if unlocked, nil if not held



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

def unlock(conn = nil)
  if conn
    do_unlock(conn)
  else
    redis(redis_pool) { |rcon| do_unlock(rcon) }
  end
end