Class: WithAdvisoryLock::PostgreSQL

Inherits:
Base
  • Object
show all
Defined in:
lib/with_advisory_lock/postgresql.rb

Instance Attribute Summary

Attributes inherited from Base

#connection, #disable_query_cache, #lock_name, #shared, #timeout_seconds, #transaction

Instance Method Summary collapse

Methods inherited from Base

#already_locked?, #initialize, #lock_and_yield, lock_stack, #lock_stack_item, #lock_str, #stable_hashcode, #unique_column_name, #with_advisory_lock_if_needed, #yield_with_lock, #yield_with_lock_and_timeout

Constructor Details

This class inherits a constructor from WithAdvisoryLock::Base

Instance Method Details

#execute_successful?(pg_function) ⇒ Boolean

Returns:

  • (Boolean)


27
28
29
30
31
32
33
# File 'lib/with_advisory_lock/postgresql.rb', line 27

def execute_successful?(pg_function)
  comment = lock_name.to_s.gsub(%r{(/\*)|(\*/)}, '--')
  sql = "SELECT #{pg_function}(#{lock_keys.join(',')}) AS #{unique_column_name} /* #{comment} */"
  result = connection.select_value(sql)
  # MRI returns 't', jruby returns true. YAY!
  ['t', true].include?(result)
end

#lock_keysObject

PostgreSQL wants 2 32bit integers as the lock key.



36
37
38
39
40
41
# File 'lib/with_advisory_lock/postgresql.rb', line 36

def lock_keys
  @lock_keys ||= [stable_hashcode(lock_name), ENV['WITH_ADVISORY_LOCK_PREFIX']].map do |ea|
    # pg advisory args must be 31 bit ints
    ea.to_i & 0x7fffffff
  end
end

#release_lockObject



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/with_advisory_lock/postgresql.rb', line 11

def release_lock
  return if transaction

  pg_function = "pg_advisory_unlock#{shared ? '_shared' : ''}"
  execute_successful?(pg_function)
rescue ActiveRecord::StatementInvalid => e
  raise unless e.message =~ / ERROR: +current transaction is aborted,/

  begin
    connection.rollback_db_transaction
    execute_successful?(pg_function)
  ensure
    connection.begin_db_transaction
  end
end

#try_lockObject



6
7
8
9
# File 'lib/with_advisory_lock/postgresql.rb', line 6

def try_lock
  pg_function = "pg_try_advisory#{transaction ? '_xact' : ''}_lock#{shared ? '_shared' : ''}"
  execute_successful?(pg_function)
end