Class: Locker
- Inherits:
-
Object
- Object
- Locker
- Defined in:
- lib/locker/locker.rb,
lib/locker/version.rb,
lib/locker/advisory.rb
Defined Under Namespace
Classes: Advisory, LockStolen
Constant Summary collapse
- VERSION =
"0.4.0"
Class Attribute Summary collapse
-
.model ⇒ Object
Returns the value of attribute model.
Instance Attribute Summary collapse
-
#blocking ⇒ Object
Returns the value of attribute blocking.
-
#identifier ⇒ Object
Returns the value of attribute identifier.
-
#key ⇒ Object
Returns the value of attribute key.
-
#lock_for ⇒ Object
Returns the value of attribute lock_for.
-
#locked ⇒ Object
Returns the value of attribute locked.
-
#model ⇒ Object
Returns the value of attribute model.
-
#renew_every ⇒ Object
Returns the value of attribute renew_every.
Class Method Summary collapse
Instance Method Summary collapse
- #get ⇒ Object
-
#initialize(key, options = {}) ⇒ Locker
constructor
A new instance of Locker.
- #release ⇒ Object
- #renew(thread = Thread.current) ⇒ Object
- #run(blocking = @blocking, &block) ⇒ Object
- #sequence ⇒ Object
Constructor Details
#initialize(key, options = {}) ⇒ Locker
Returns a new instance of Locker.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/locker/locker.rb', line 13 def initialize(key, ={}) @identifier = "host:#{Socket.gethostname} pid:#{Process.pid} guid:#{SecureRandom.hex(16)}" rescue "pid:#{Process.pid} guid:#{SecureRandom.hex(16)}" @key = key @renew_every = ([:renew_every] || 10.seconds).to_f @lock_for = ([:lock_for] || 30.seconds).to_f @model = ([:model] || self.class.model || ::Lock) @blocking = !![: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
.model ⇒ Object
Returns the value of attribute model.
10 11 12 |
# File 'lib/locker/locker.rb', line 10 def model @model end |
Instance Attribute Details
#blocking ⇒ Object
Returns the value of attribute blocking.
7 8 9 |
# File 'lib/locker/locker.rb', line 7 def blocking @blocking end |
#identifier ⇒ Object
Returns the value of attribute identifier.
7 8 9 |
# File 'lib/locker/locker.rb', line 7 def identifier @identifier end |
#key ⇒ Object
Returns the value of attribute key.
7 8 9 |
# File 'lib/locker/locker.rb', line 7 def key @key end |
#lock_for ⇒ Object
Returns the value of attribute lock_for.
7 8 9 |
# File 'lib/locker/locker.rb', line 7 def lock_for @lock_for end |
#locked ⇒ Object
Returns the value of attribute locked.
7 8 9 |
# File 'lib/locker/locker.rb', line 7 def locked @locked end |
#model ⇒ Object
Returns the value of attribute model.
7 8 9 |
# File 'lib/locker/locker.rb', line 7 def model @model end |
#renew_every ⇒ Object
Returns the value of attribute renew_every.
7 8 9 |
# File 'lib/locker/locker.rb', line 7 def renew_every @renew_every end |
Class Method Details
.run(key, options = {}, &block) ⇒ Object
29 30 31 32 |
# File 'lib/locker/locker.rb', line 29 def self.run(key, ={}, &block) locker = new(key, ) locker.run(&block) end |
Instance Method Details
#get ⇒ Object
62 63 64 65 66 |
# File 'lib/locker/locker.rb', line 62 def get @locked = updated?(model. where(["key = ? AND (locked_by IS NULL OR locked_by = ? OR locked_until < clock_timestamp() at time zone 'UTC')", @key, @identifier]). update_all(["locked_by = ?, locked_at = clock_timestamp() at time zone 'UTC', locked_until = clock_timestamp() at time zone 'UTC' + #{lock_interval}, sequence = sequence + 1", @identifier])) end |
#release ⇒ Object
68 69 70 71 72 |
# File 'lib/locker/locker.rb', line 68 def release @locked = updated?(model. where(["key = ? and locked_by = ?", @key, @identifier]). update_all(["locked_by = NULL"])) end |
#renew(thread = Thread.current) ⇒ Object
74 75 76 77 78 79 80 |
# File 'lib/locker/locker.rb', line 74 def renew(thread=Thread.current) @locked = updated?(model. where(["key = ? and locked_by = ?", @key, @identifier]). update_all(["locked_until = clock_timestamp() at time zone 'UTC' + #{lock_interval}"])) thread.raise LockStolen unless @locked @locked end |
#run(blocking = @blocking, &block) ⇒ Object
34 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 |
# File 'lib/locker/locker.rb', line 34 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(sequence) ensure renewer.exit rescue nil release if @locked end true else false end end |
#sequence ⇒ Object
82 83 84 85 86 87 88 89 |
# File 'lib/locker/locker.rb', line 82 def sequence if @sequence @sequence else record = model.find_by_key_and_locked_by(@key, @identifier) @sequence = record && record.sequence end end |