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]