Module: WithAdvisoryLock::CoreAdvisory
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/with_advisory_lock/core_advisory.rb
Constant Summary collapse
- LOCK_PREFIX_ENV =
'WITH_ADVISORY_LOCK_PREFIX'
Instance Method Summary collapse
-
#advisory_lock_stack ⇒ Object
Thread-local lock stack management.
- #with_advisory_lock_if_needed(lock_name, options = {}, &block) ⇒ Object
Instance Method Details
#advisory_lock_stack ⇒ Object
Thread-local lock stack management
12 13 14 |
# File 'lib/with_advisory_lock/core_advisory.rb', line 12 def advisory_lock_stack Thread.current[:with_advisory_lock_stack] ||= [] end |
#with_advisory_lock_if_needed(lock_name, options = {}, &block) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 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 |
# File 'lib/with_advisory_lock/core_advisory.rb', line 16 def with_advisory_lock_if_needed(lock_name, = {}, &block) = { timeout_seconds: } unless .respond_to?(:fetch) .assert_valid_keys :timeout_seconds, :shared, :transaction, :disable_query_cache # Validate transaction-level locks are used within a transaction if .fetch(:transaction, false) && !transaction_open? raise ArgumentError, 'transaction-level advisory locks require an active transaction' end lock_str = "#{ENV.fetch(LOCK_PREFIX_ENV, nil)}#{lock_name}" lock_stack_item = LockStackItem.new(lock_str, .fetch(:shared, false)) if advisory_lock_stack.include?(lock_stack_item) # Already have this exact lock (same name and type), just yield return Result.new(lock_was_acquired: true, result: yield) end # Check if we have a lock with the same name but different type (for upgrade/downgrade) same_name_different_type = advisory_lock_stack.any? do |item| item.name == lock_str && item.shared != .fetch(:shared, false) end if same_name_different_type && .fetch(:transaction, false) # PostgreSQL doesn't support upgrading/downgrading transaction-level locks return Result.new(lock_was_acquired: false) end disable_query_cache = .fetch(:disable_query_cache, false) if disable_query_cache uncached do advisory_lock_and_yield(lock_name, lock_str, lock_stack_item, , &block) end else advisory_lock_and_yield(lock_name, lock_str, lock_stack_item, , &block) end end |