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:

Constant Summary collapse

CLOCK_DRIFT_FACTOR =

Returns used to take into consideration the inaccuracy of redis timestamps.

Returns:

  • (Float)

    used to take into consideration the inaccuracy of redis timestamps

0.01
NETWORK_FACTOR =
0.04

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, 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

Options Hash (item):



63
64
65
66
67
68
69
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 63

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

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



48
49
50
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 48

def config
  @config
end

#itemObject (readonly)

Returns the value of attribute item.



52
53
54
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 52

def item
  @item
end

#job_idObject (readonly)

Returns the value of attribute job_id.



44
45
46
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 44

def job_id
  @job_id
end

#keyObject (readonly)

Returns the value of attribute key.



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

def key
  @key
end

Instance Method Details

#==(other) ⇒ true, false

Compare this locksmith with another

Parameters:

  • other (Locksmith)

    the locksmith to compare with

Returns:

  • (true, false)


172
173
174
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 172

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

#deleteObject

Deletes the lock unless it has a pttl set



75
76
77
78
79
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 75

def delete
  return if config.pttl.positive?

  delete!
end

#delete!Object

Deletes the lock regardless of if it has a pttl set



84
85
86
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 84

def delete!
  call_script(:delete, key.to_a, [job_id, config.pttl, config.type, config.limit]).to_i.positive?
end

#execute(&block) ⇒ Object



102
103
104
105
106
107
108
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 102

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

  redis(redis_pool) do |conn|
    lock!(conn, method(:primed_async), &block)
  end
end

#inspectObject

See Also:



161
162
163
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 161

def inspect
  to_s
end

#lock(wait: nil) ⇒ String

Create a lock for the Sidekiq job

Returns:

  • (String)

    the Sidekiq job_id that was locked/queued



93
94
95
96
97
98
99
100
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 93

def lock(wait: nil)
  method_name = wait ? :primed_async : :primed_sync
  redis(redis_pool) do |conn|
    lock!(conn, method(method_name), wait) do
      return job_id
    end
  end
end

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

Checks if this instance is considered locked

Parameters:

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

    the redis connection

Returns:

  • (true, false)

    true when the :LOCKED hash contains the job_id



142
143
144
145
146
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 142

def locked?(conn = nil)
  return taken?(conn) if conn

  redis { |rcon| taken?(rcon) }
end

#to_sString

Nicely formatted string with information about self

Returns:

  • (String)


154
155
156
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 154

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

#unlock(conn = 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



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

def unlock(conn = nil)
  return false unless locked?(conn)

  unlock!(conn)
end

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

Removes the lock keys from Redis

Returns:

  • (false)

    unless locked?

  • (String)

    Sidekiq job_id (jid) if successful



128
129
130
131
132
133
134
# File 'lib/sidekiq_unique_jobs/locksmith.rb', line 128

def unlock!(conn = nil)
  call_script(:unlock, key.to_a, argv, conn) do |unlocked_jid|
    reflect(:debug, :unlocked, item, unlocked_jid) if unlocked_jid == job_id

    unlocked_jid
  end
end