lib/good_job/lockable.rb in good_job-1.3.5 vs lib/good_job/lockable.rb in good_job-1.3.6
- old
+ new
@@ -139,38 +139,39 @@
records.each(&:advisory_unlock)
end
end
def supports_cte_materialization_specifiers?
- return @supports_cte_materialization_specifiers if defined?(@supports_cte_materialization_specifiers)
+ return @_supports_cte_materialization_specifiers if defined?(@_supports_cte_materialization_specifiers)
- @supports_cte_materialization_specifiers = ActiveRecord::Base.connection.postgresql_version >= 120000
+ @_supports_cte_materialization_specifiers = ActiveRecord::Base.connection.postgresql_version >= 120000
end
end
# Acquires an advisory lock on this record if it is not already locked by
# another database session. Be careful to ensure you release the lock when
# you are done with {#advisory_unlock} (or {#advisory_unlock!} to release
# all remaining locks).
# @return [Boolean] whether the lock was acquired.
def advisory_lock
- where_sql = <<~SQL.squish
- pg_try_advisory_lock(('x' || substr(md5(:table_name || :id::text), 1, 16))::bit(64)::bigint)
+ query = <<~SQL.squish
+ SELECT 1 AS one
+ WHERE pg_try_advisory_lock(('x'||substr(md5($1 || $2::text), 1, 16))::bit(64)::bigint)
SQL
- self.class.unscoped.exists?([where_sql, { table_name: self.class.table_name, id: send(self.class.primary_key) }])
+ self.class.connection.exec_query(query, 'GoodJob::Lockable Advisory Lock', [[nil, self.class.table_name], [nil, send(self.class.primary_key)]]).any?
end
# 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.
# @return [Boolean] whether the lock was released.
def advisory_unlock
query = <<~SQL.squish
SELECT 1 AS one
- WHERE pg_advisory_unlock(('x'||substr(md5(:table_name || :id::text), 1, 16))::bit(64)::bigint)
+ WHERE pg_advisory_unlock(('x'||substr(md5($1 || $2::text), 1, 16))::bit(64)::bigint)
SQL
- self.class.connection.execute(sanitize_sql_for_conditions([query, { table_name: self.class.table_name, id: send(self.class.primary_key) }])).ntuples.positive?
+ self.class.connection.exec_query(query, 'GoodJob::Lockable Advisory Unlock', [[nil, self.class.table_name], [nil, send(self.class.primary_key)]]).any?
end
# Acquires an advisory lock on this record or raises
# {RecordAlreadyAdvisoryLockedError} if it is already locked by another
# database session.
@@ -203,16 +204,33 @@
end
# Tests whether this record has an advisory lock on it.
# @return [Boolean]
def advisory_locked?
- self.class.unscoped.advisory_locked.exists?(id: send(self.class.primary_key))
+ query = <<~SQL.squish
+ SELECT 1 AS one
+ FROM pg_locks
+ WHERE pg_locks.locktype = 'advisory'
+ AND pg_locks.objsubid = 1
+ AND pg_locks.classid = ('x' || substr(md5($1 || $2::text), 1, 16))::bit(32)::int
+ AND pg_locks.objid = (('x' || substr(md5($1 || $2::text), 1, 16))::bit(64) << 32)::bit(32)::int
+ SQL
+ self.class.connection.exec_query(query, 'GoodJob::Lockable Advisory Locked?', [[nil, self.class.table_name], [nil, send(self.class.primary_key)]]).any?
end
# Tests whether this record is locked by the current database session.
# @return [Boolean]
def owns_advisory_lock?
- self.class.unscoped.owns_advisory_locked.exists?(id: send(self.class.primary_key))
+ query = <<~SQL.squish
+ SELECT 1 AS one
+ FROM pg_locks
+ WHERE pg_locks.locktype = 'advisory'
+ AND pg_locks.objsubid = 1
+ AND pg_locks.classid = ('x' || substr(md5($1 || $2::text), 1, 16))::bit(32)::int
+ AND pg_locks.objid = (('x' || substr(md5($1 || $2::text), 1, 16))::bit(64) << 32)::bit(32)::int
+ AND pg_locks.pid = pg_backend_pid()
+ SQL
+ self.class.connection.exec_query(query, 'GoodJob::Lockable Owns Advisory Lock?', [[nil, self.class.table_name], [nil, send(self.class.primary_key)]]).any?
end
# Releases all advisory locks on the record that are held by the current
# database session.
# @return [void]