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
- AREL_TABLE_NEW_KWARGS =
Arel::Table.instance_method(:initialize).parameters.any? { |type, name| type == :key && name == :name }
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.
674 675 676 677 678 679 680 681 682 683 684 685 686 687 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 674 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.
706 707 708 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 706 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.
720 721 722 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 720 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.
695 696 697 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 695 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.
743 744 745 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 743 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.
727 728 729 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 727 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
755 756 757 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 755 def lockable_column_key(column: self.class._advisory_lockable_column) "#{self.class.table_name}-#{self[column]}" end |
#lockable_key ⇒ String
Default Advisory Lock key
749 750 751 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 749 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.
734 735 736 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 734 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.
711 712 713 714 715 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 711 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 |