Module: Sequel::Postgres::PgAdvisoryLock
- Defined in:
- lib/sequel/extensions/pg_advisory_lock.rb
Constant Summary collapse
- SESSION_LEVEL_LOCKS =
[ :pg_advisory_lock, :pg_try_advisory_lock ].freeze
- TRANSACTION_LEVEL_LOCKS =
[ :pg_advisory_xact_lock, :pg_try_advisory_xact_lock ].freeze
- LOCK_FUNCTIONS =
(SESSION_LEVEL_LOCKS + TRANSACTION_LEVEL_LOCKS).freeze
- DEFAULT_LOCK_FUNCTION =
:pg_advisory_lock- UNLOCK_FUNCTION =
:pg_advisory_unlock
Instance Method Summary collapse
- #advisory_lock_key_for(lock_name) ⇒ Object
- #register_advisory_lock(name, lock_function = DEFAULT_LOCK_FUNCTION) ⇒ Object
- #registered_advisory_locks ⇒ Object
- #with_advisory_lock(name, id = nil, &block) ⇒ Object
Instance Method Details
#advisory_lock_key_for(lock_name) ⇒ Object
81 82 83 |
# File 'lib/sequel/extensions/pg_advisory_lock.rb', line 81 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) ⇒ Object
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/sequel/extensions/pg_advisory_lock.rb', line 61 def register_advisory_lock(name, lock_function = DEFAULT_LOCK_FUNCTION) name = name.to_sym if registered_advisory_locks.key?(name) raise Error, "Lock with name :#{name} is already registered" end key = advisory_lock_key_for(name) if registered_advisory_locks.values.any? { |opts| opts.fetch(:key) == key } 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 ⇒ Object
23 24 25 |
# File 'lib/sequel/extensions/pg_advisory_lock.rb', line 23 def registered_advisory_locks @registered_advisory_locks ||= {} end |
#with_advisory_lock(name, id = nil, &block) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/sequel/extensions/pg_advisory_lock.rb', line 27 def with_advisory_lock(name, id = nil, &block) = registered_advisory_locks.fetch(name.to_sym) lock_key = .fetch(:key) function_params = [lock_key, id].compact lock_function = .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 |