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
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.
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.
606 607 608 609 610 611 612 613 614 615 616 617 618 619 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 606 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.
638 639 640 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 638 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.
652 653 654 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 652 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.
627 628 629 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 627 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.
675 676 677 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 675 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.
659 660 661 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 659 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
687 688 689 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 687 def lockable_column_key(column: self.class._advisory_lockable_column) "#{self.class.table_name}-#{self[column]}" end |
#lockable_key ⇒ String
Default Advisory Lock key
681 682 683 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 681 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.
666 667 668 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 666 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.
643 644 645 646 647 |
# File 'app/models/concerns/good_job/advisory_lockable.rb', line 643 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 |