Skip to content

Commit

Permalink
Merge pull request #188 from bensheldon/lockable_locked
Browse files Browse the repository at this point in the history
Have Lockable#advisory_locked? directly query pg_locks table
  • Loading branch information
bensheldon authored Dec 30, 2020
2 parents 13fb7fc + 0b7a6cd commit bed770d
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 2 deletions.
10 changes: 9 additions & 1 deletion lib/good_job/lockable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,15 @@ def with_advisory_lock
# 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(:table_name || :id::text), 1, 16))::bit(32)::int
AND pg_locks.objid = (('x' || substr(md5(:table_name || :id::text), 1, 16))::bit(64) << 32)::bit(32)::int
SQL
self.class.connection.execute(sanitize_sql_for_conditions([query, { table_name: self.class.table_name, id: send(self.class.primary_key) }])).ntuples.positive?
end

# Tests whether this record is locked by the current database session.
Expand Down
21 changes: 20 additions & 1 deletion spec/lib/good_job/lockable_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,26 @@

expect do
job.advisory_unlock
end.to change(PgLock, :count).by(-1)
end.to change(job, :advisory_locked?).from(true).to(false)
end
end

describe '#advisory_locked?' do
it 'reflects whether the record is locked' do
expect(job.advisory_locked?).to eq false
job.advisory_lock
expect(job.advisory_locked?).to eq true
job.advisory_unlock
expect(job.advisory_locked?).to eq false
end

it 'is accurate even if the job has been destroyed' do
job.advisory_lock
expect(job.advisory_locked?).to eq true
job.destroy!
expect(job.advisory_locked?).to eq true
job.advisory_unlock
expect(job.advisory_locked?).to eq false
end
end

Expand Down

0 comments on commit bed770d

Please sign in to comment.