Class: Locker

Inherits:
Object
  • Object
show all
Defined in:
lib/locker/locker.rb,
lib/locker/version.rb

Defined Under Namespace

Classes: LockStolen

Constant Summary collapse

SecureRandom =
ActiveSupport::SecureRandom
VERSION =
"0.0.3"

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, options = {}) ⇒ Locker

Returns a new instance of Locker.

Raises:

  • (ArgumentError)


14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/locker/locker.rb', line 14

def initialize(key, options={})
  @identifier  = "host:#{Socket.gethostname} pid:#{Process.pid} guid:#{SecureRandom.hex(16)}" rescue "pid:#{Process.pid} guid:#{SecureRandom.hex(16)}"
  @key         = key
  @renew_every = (options[:renew_every] || 10.seconds).to_f
  @lock_for    = (options[:lock_for] || 30.seconds).to_f
  @model       = (options[:model] || self.class.model || ::Lock)
  @blocking    = !!options[:blocking]
  @locked      = false

  raise ArgumentError, "renew_every must be greater than 0" if @renew_every <= 0
  raise ArgumentError, "lock_for must be greater than 0" if @lock_for <= 0
  raise ArgumentError, "renew_every must be less than lock_for" if @renew_every >= @lock_for

  ensure_key_exists
end

Class Attribute Details

.modelObject

Returns the value of attribute model.



11
12
13
# File 'lib/locker/locker.rb', line 11

def model
  @model
end

Instance Attribute Details

#blockingObject

Returns the value of attribute blocking.



8
9
10
# File 'lib/locker/locker.rb', line 8

def blocking
  @blocking
end

#identifierObject

Returns the value of attribute identifier.



8
9
10
# File 'lib/locker/locker.rb', line 8

def identifier
  @identifier
end

#keyObject

Returns the value of attribute key.



8
9
10
# File 'lib/locker/locker.rb', line 8

def key
  @key
end

#lock_forObject

Returns the value of attribute lock_for.



8
9
10
# File 'lib/locker/locker.rb', line 8

def lock_for
  @lock_for
end

#lockedObject

Returns the value of attribute locked.



8
9
10
# File 'lib/locker/locker.rb', line 8

def locked
  @locked
end

#modelObject

Returns the value of attribute model.



8
9
10
# File 'lib/locker/locker.rb', line 8

def model
  @model
end

#renew_everyObject

Returns the value of attribute renew_every.



8
9
10
# File 'lib/locker/locker.rb', line 8

def renew_every
  @renew_every
end

Class Method Details

.run(key, options = {}, &block) ⇒ Object



30
31
32
33
# File 'lib/locker/locker.rb', line 30

def self.run(key, options={}, &block)
  locker = new(key, options)
  locker.run(&block)
end

Instance Method Details

#getObject



63
64
65
66
# File 'lib/locker/locker.rb', line 63

def get
  @locked = update_all(["locked_by = ?, locked_at = clock_timestamp() at time zone 'UTC', locked_until = clock_timestamp() at time zone 'UTC' + #{lock_interval}", @identifier],
                       ["key = ? AND (locked_by IS NULL OR locked_by = ? OR locked_until < clock_timestamp() at time zone 'UTC')", @key, @identifier])
end

#releaseObject



68
69
70
# File 'lib/locker/locker.rb', line 68

def release
  @locked = update_all(["locked_by = NULL"],["key = ? and locked_by = ?", @key, @identifier])
end

#renew(thread = Thread.current) ⇒ Object



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

def renew(thread=Thread.current)
  @locked = update_all(["locked_until = clock_timestamp() at time zone 'UTC' + #{lock_interval}"], ["key = ? and locked_by = ?", @key, @identifier])
  thread.raise LockStolen unless @locked
  @locked
end

#run(blocking = @blocking, &block) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/locker/locker.rb', line 35

def run(blocking=@blocking, &block)
  while !get && blocking
    sleep 0.5
  end

  if @locked
    begin
      parent_thread = Thread.current

      renewer = Thread.new do
        while @locked
          sleep @renew_every
          renew(parent_thread)
        end
      end

      block.call
    ensure
      renewer.exit rescue nil
      release if @locked
    end

    true
  else
    false
  end
end