Class: SidekiqUniqueJobs::Lock

Inherits:
Object
  • Object
show all
Includes:
Connection, JSON, Timing
Defined in:
lib/sidekiq_unique_jobs/lock.rb,
lib/sidekiq_unique_jobs/lock/base_lock.rb,
lib/sidekiq_unique_jobs/lock/validator.rb,
lib/sidekiq_unique_jobs/lock/until_expired.rb,
lib/sidekiq_unique_jobs/lock/until_executed.rb,
lib/sidekiq_unique_jobs/lock/until_executing.rb,
lib/sidekiq_unique_jobs/lock/while_executing.rb,
lib/sidekiq_unique_jobs/lock/client_validator.rb,
lib/sidekiq_unique_jobs/lock/server_validator.rb,
lib/sidekiq_unique_jobs/lock/while_executing_reject.rb,
lib/sidekiq_unique_jobs/lock/until_and_while_executing.rb

Overview

Class Lock provides access to information about a lock

Author:

  • Mikael Henriksson <mikael@mhenrixon.com>

Defined Under Namespace

Classes: BaseLock, ClientValidator, LockInfoStub, ServerValidator, UntilAndWhileExecuting, UntilExecuted, UntilExecuting, UntilExpired, Validator, WhileExecuting, WhileExecutingReject

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from JSON

dump_json, load_json, safe_load_json

Methods included from Timing

clock_stamp, now_f, time_source, timed

Methods included from Connection

included, #redis

Constructor Details

#initialize(key, time: nil) ⇒ Lock

Initialize a new lock

Parameters:

  • key (String, Key)

    either a digest or an instance of a Key

  • time (Float) (defaults to: nil)

    optional timestamp to initiate this lock with



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

def initialize(key, time: nil)
  @key = key.is_a?(SidekiqUniqueJobs::Key) ? key : SidekiqUniqueJobs::Key.new(key)
  time = time.to_f unless time.is_a?(Float)
  return unless time.nonzero?

  @created_at = time
end

Instance Attribute Details

#keyObject (readonly)

Returns the value of attribute key.



16
17
18
# File 'lib/sidekiq_unique_jobs/lock.rb', line 16

def key
  @key
end

Class Method Details

.create(digest, job_id, lock_info: {}, time: Timing.now_f, score: nil) ⇒ Lock

Initialize a locked lock

Parameters:

  • digest (String)

    a unique digest

  • job_id (String)

    a sidekiq JID

  • lock_info (Hash) (defaults to: {})

    information about the lock

Returns:

  • (Lock)

    a newly lock that has been locked



27
28
29
30
31
# File 'lib/sidekiq_unique_jobs/lock.rb', line 27

def self.create(digest, job_id, lock_info: {}, time: Timing.now_f, score: nil)
  lock = new(digest, time: time)
  lock.lock(job_id, lock_info, score)
  lock
end

Instance Method Details

#created_atFloat

Returns either the initialized time or the earliest lock timestamp

Returns:

  • (Float)

    a timestamp



106
107
108
109
110
111
# File 'lib/sidekiq_unique_jobs/lock.rb', line 106

def created_at
  return @created_at if @created_at

  first_entry = locked_jids(with_values: true).values.first
  @created_at = first_entry ? (first_entry) : now_f
end

#delvoid

This method returns an undefined value.

Deletes all the redis keys for this lock



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

def del
  redis do |conn|
    conn.multi do |pipeline|
      pipeline.call("ZREM", DIGESTS, key.digest)
      pipeline.call("UNLINK", key.locked)
    end
  end
end

#infoHash?

Returns lock metadata from the LOCKED hash value (JSON)

Returns:

  • (Hash, nil)

    parsed metadata or nil



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

def info
  @info ||= build_info
end

#inspectObject



147
148
149
# File 'lib/sidekiq_unique_jobs/lock.rb', line 147

def inspect
  to_s
end

#lock(job_id, lock_info = {}, score = nil) ⇒ void

This method returns an undefined value.

Locks a job_id

Parameters:

  • job_id (String)

    a sidekiq JID

  • lock_info (Hash) (defaults to: {})

    information about the lock

  • score (Float) (defaults to: nil)

    the ZADD score



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

def lock(job_id, lock_info = {}, score = nil)
  score ||= now_f
   = dump_json(lock_info.merge("time" => @created_at || now_f))

  redis do |conn|
    conn.multi do |pipeline|
      pipeline.call("HSET", key.locked, job_id, )
      pipeline.call("ZADD", key.digests, score.to_s, key.digest)
    end
  end
end

#lockedRedis::Hash

The locked hash

Returns:



139
140
141
# File 'lib/sidekiq_unique_jobs/lock.rb', line 139

def locked
  @locked ||= Redis::Hash.new(key.locked)
end

#locked_jids(with_values: false) ⇒ Hash<String, String>, Array<String>

Returns a collection of locked job_id’s

Parameters:

  • with_values (true, false) (defaults to: false)

    provide the metadata for each lock

Returns:

  • (Hash<String, String>)

    when given ‘with_values: true`

  • (Array<String>)

    when given ‘with_values: false`



121
122
123
# File 'lib/sidekiq_unique_jobs/lock.rb', line 121

def locked_jids(with_values: false)
  locked.entries(with_values: with_values)
end

#to_sObject



143
144
145
# File 'lib/sidekiq_unique_jobs/lock.rb', line 143

def to_s
  "Lock(#{key.digest})"
end

#unlock(job_id) ⇒ Integer

Unlock a specific job_id

Parameters:

  • job_id (String)

    a sidekiq JID

Returns:

  • (Integer)

    number of fields removed



75
76
77
78
79
80
81
82
83
84
85
# File 'lib/sidekiq_unique_jobs/lock.rb', line 75

def unlock(job_id)
  locked.del(job_id)

  # Clean up digests ZSET when no more holders
  redis do |conn|
    if conn.call("HLEN", key.locked).zero?
      conn.call("ZREM", DIGESTS, key.digest)
      conn.call("UNLINK", key.locked)
    end
  end
end