Module: GoodJob::AdvisoryLockable
- Extended by:
- ActiveSupport::Concern
- Included in:
- BatchRecord, Job, Process
- Defined in:
- app/models/concerns/good_job/advisory_lockable.rb
Overview
Adds Postgres advisory locking capabilities to an ActiveRecord record. For details on advisory locks, see the Postgres documentation:
Defined Under Namespace
Classes: AdvisoryLockCounter
Constant Summary collapse
- RecordAlreadyAdvisoryLockedError =
Indicates an advisory lock is already held on a record by another database session.
Class.new(StandardError)
- ADVISORY_LOCK_COUNTS =
AdvisoryLockCounter.new
Class Method Summary collapse
Instance Method Summary collapse
-
#advisory_lock(key: lockable_key, function: advisory_lockable_function, connection: nil, &block) ⇒ Boolean, Object
Acquires an advisory lock on this record if it is not already locked by another database session.
-
#advisory_lock!(key: lockable_key, function: advisory_lockable_function, connection: nil) ⇒ Boolean
Acquires an advisory lock on this record or raises RecordAlreadyAdvisoryLockedError if it is already locked by another database session.
-
#advisory_locked?(key: lockable_key) ⇒ Boolean
Tests whether this record has an advisory lock on it.
-
#advisory_unlock(key: lockable_key, function: self.class.advisory_unlockable_function(advisory_lockable_function), connection: nil) ⇒ Boolean
Releases an advisory lock on this record if it is locked by this database session.
-
#advisory_unlock!(key: lockable_key, function: self.class.advisory_unlockable_function) ⇒ void
Releases all advisory locks on the record that are held by the current database session.
-
#advisory_unlocked?(key: lockable_key) ⇒ Boolean
Tests whether this record does not have an advisory lock on it.
-
#lockable_column_key(column: self.class._advisory_lockable_column) ⇒ String
Default Advisory Lock key for column-based locking.
-
#lockable_key ⇒ String
Default Advisory Lock key.
-
#owns_advisory_lock?(key: lockable_key) ⇒ Boolean
Tests whether this record is locked by the current database session.
-
#with_advisory_lock(key: lockable_key, function: advisory_lockable_function, &block) ⇒ Object
deprecated
Deprecated.
Use #advisory_lock with a block instead.
Class Method Details
.hash_function ⇒ Object
38 39 40 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 38 def hash_function @_hash_function ||= "md5" end |
.hash_function=(value) ⇒ Object
34 35 36 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 34 def hash_function=(value) @_hash_function = value end |
Instance Method Details
#advisory_lock(key: lockable_key, function: advisory_lockable_function, connection: nil, &block) ⇒ Boolean, Object
Acquires an advisory lock on this record if it is not already locked by another database session.
Without a block, acquires the lock and returns true/false. The caller is responsible for releasing with #advisory_unlock.
With a block, acquires the lock (raising RecordAlreadyAdvisoryLockedError if it cannot), yields, and releases the lock when the block completes.
666 667 668 669 670 671 672 673 674 675 676 677 678 679 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 666 def advisory_lock(key: lockable_key, function: advisory_lockable_function, connection: nil, &block) if block acquired = false result = self.class.advisory_lock_key(key, function: function, connection: connection) do acquired = true yield end raise RecordAlreadyAdvisoryLockedError unless acquired result else self.class.advisory_lock_key(key, function: function, connection: connection) end end |
#advisory_lock!(key: lockable_key, function: advisory_lockable_function, connection: nil) ⇒ Boolean
Acquires an advisory lock on this record or raises RecordAlreadyAdvisoryLockedError if it is already locked by another database session.
698 699 700 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 698 def advisory_lock!(key: lockable_key, function: advisory_lockable_function, connection: nil) advisory_lock(key: key, function: function, connection: connection) || raise(RecordAlreadyAdvisoryLockedError) end |
#advisory_locked?(key: lockable_key) ⇒ Boolean
Tests whether this record has an advisory lock on it.
712 713 714 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 712 def advisory_locked?(key: lockable_key) self.class.advisory_locked_key?(key) end |
#advisory_unlock(key: lockable_key, function: self.class.advisory_unlockable_function(advisory_lockable_function), connection: nil) ⇒ Boolean
Releases an advisory lock on this record if it is locked by this database session. Note that advisory locks stack, so you must call #advisory_unlock and #advisory_lock the same number of times.
687 688 689 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 687 def advisory_unlock(key: lockable_key, function: self.class.advisory_unlockable_function(advisory_lockable_function), connection: nil) self.class.advisory_unlock_key(key, function: function, connection: connection || self.class.lease_connection) end |
#advisory_unlock!(key: lockable_key, function: self.class.advisory_unlockable_function) ⇒ void
This method returns an undefined value.
Releases all advisory locks on the record that are held by the current database session.
735 736 737 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 735 def advisory_unlock!(key: lockable_key, function: self.class.advisory_unlockable_function) self.class.advisory_unlock_key!(key, function: function) end |
#advisory_unlocked?(key: lockable_key) ⇒ Boolean
Tests whether this record does not have an advisory lock on it.
719 720 721 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 719 def advisory_unlocked?(key: lockable_key) !advisory_locked?(key: key) end |
#lockable_column_key(column: self.class._advisory_lockable_column) ⇒ String
Default Advisory Lock key for column-based locking
747 748 749 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 747 def lockable_column_key(column: self.class._advisory_lockable_column) "#{self.class.table_name}-#{self[column]}" end |
#lockable_key ⇒ String
Default Advisory Lock key
741 742 743 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 741 def lockable_key lockable_column_key end |
#owns_advisory_lock?(key: lockable_key) ⇒ Boolean
Tests whether this record is locked by the current database session.
726 727 728 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 726 def owns_advisory_lock?(key: lockable_key) self.class.owns_advisory_lock_key?(key) end |
#with_advisory_lock(key: lockable_key, function: advisory_lockable_function, &block) ⇒ Object
Use #advisory_lock with a block instead.
703 704 705 706 707 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 703 def with_advisory_lock(key: lockable_key, function: advisory_lockable_function, &block) raise ArgumentError, "Must provide a block" unless block advisory_lock(key: key, function: function, &block) end |