module Sequel::Postgres::PgAdvisoryLock
Constants
- DEFAULT_LOCK_FUNCTION
- LOCK_FUNCTIONS
- SESSION_LEVEL_LOCKS
- TRANSACTION_LEVEL_LOCKS
- UNLOCK_FUNCTION
Public Instance Methods
advisory_lock_key_for(lock_name)
click to toggle source
# File lib/sequel/extensions/pg_advisory_lock.rb, line 94 def advisory_lock_key_for(lock_name) Zlib.crc32(lock_name.to_s) % 2 ** 31 end
register_advisory_lock(name, lock_function = DEFAULT_LOCK_FUNCTION)
click to toggle source
Beth: not sure how much extra value this registration provides. It turns the name into a number, and makes sure the name/number is unique, and that you don’t try and use a different lock function with the same name.
# File lib/sequel/extensions/pg_advisory_lock.rb, line 73 def register_advisory_lock(name, lock_function = DEFAULT_LOCK_FUNCTION) name = name.to_sym if registered_advisory_locks.key?(name) && registered_advisory_locks[name][:lock_function] != lock_function raise LockAlreadyRegistered, "Lock with name :#{name} is already registered with a different lock function (#{registered_advisory_locks[name][:lock_function]})" end key = advisory_lock_key_for(name) name_for_key = registered_advisory_locks.keys.find { |n| registered_advisory_locks[n].fetch(:key) == key } if name_for_key && name_for_key != name raise Error, "Lock key #{key} is already taken" end function = lock_function.to_sym unless LOCK_FUNCTIONS.include?(function) raise Error, "Invalid lock function :#{function}" end registered_advisory_locks[name] = { key: key, lock_function: function } end
registered_advisory_locks()
click to toggle source
# File lib/sequel/extensions/pg_advisory_lock.rb, line 32 def registered_advisory_locks @registered_advisory_locks ||= Concurrent::Hash.new end
with_advisory_lock(name, id = nil) { || ... }
click to toggle source
# File lib/sequel/extensions/pg_advisory_lock.rb, line 36 def with_advisory_lock(name, id = nil) options = registered_advisory_locks.fetch(name.to_sym) lock_key = options.fetch(:key) function_params = [lock_key, id].compact lock_function = options.fetch(:lock_function) transaction_level_lock = TRANSACTION_LEVEL_LOCKS.include?(lock_function) if transaction_level_lock # TODO: It's allowed to specify additional options (in particular, :server) # while opening database transaction. # That's why this check must be smarter. unless in_transaction? raise Error, "Transaction must be manually opened before using transaction level lock '#{lock_function}'" end if get(Sequel.function(lock_function, *function_params)) yield end else synchronize do if get(Sequel.function(lock_function, *function_params)) begin result = yield ensure get(Sequel.function(UNLOCK_FUNCTION, *function_params)) result end end end end end