Module: WithAdvisoryLock::MySQLAdvisory
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/with_advisory_lock/mysql_advisory.rb
Constant Summary collapse
- LOCK_PREFIX_ENV =
'WITH_ADVISORY_LOCK_PREFIX'
Instance Method Summary collapse
- #lock_keys_for(lock_name) ⇒ Object
- #release_advisory_lock(*args, **kwargs) ⇒ Object
- #supports_database_timeout? ⇒ Boolean
- #try_advisory_lock(lock_keys, lock_name:, shared:, transaction:, timeout_seconds: nil) ⇒ Object
Instance Method Details
#lock_keys_for(lock_name) ⇒ Object
56 57 58 59 |
# File 'lib/with_advisory_lock/mysql_advisory.rb', line 56 def lock_keys_for(lock_name) lock_str = "#{ENV.fetch(LOCK_PREFIX_ENV, nil)}#{lock_name}" [lock_str] end |
#release_advisory_lock(*args, **kwargs) ⇒ Object
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 |
# File 'lib/with_advisory_lock/mysql_advisory.rb', line 28 def release_advisory_lock(*args, **kwargs) # Handle both signatures - ActiveRecord's built-in and ours if args.length == 1 && kwargs.empty? # ActiveRecord's signature: release_advisory_lock(lock_id) # Called by Rails migrations with a single positional argument super else # Our signature: release_advisory_lock(lock_keys, lock_name:, **) lock_keys = args.first execute_successful?("RELEASE_LOCK(#{quote(lock_keys.first)})") end rescue ActiveRecord::StatementInvalid => e # If the connection is broken, the lock is automatically released by MySQL # No need to fail the release operation connection_lost = case e.cause when defined?(Mysql2::Error::ConnectionError) && Mysql2::Error::ConnectionError true when defined?(Trilogy::ConnectionError) && Trilogy::ConnectionError true else e. =~ /Lost connection|MySQL server has gone away|Connection refused/i end return if connection_lost raise end |
#supports_database_timeout? ⇒ Boolean
61 62 63 |
# File 'lib/with_advisory_lock/mysql_advisory.rb', line 61 def supports_database_timeout? true end |
#try_advisory_lock(lock_keys, lock_name:, shared:, transaction:, timeout_seconds: nil) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/with_advisory_lock/mysql_advisory.rb', line 11 def try_advisory_lock(lock_keys, lock_name:, shared:, transaction:, timeout_seconds: nil) raise ArgumentError, 'shared locks are not supported on MySQL' if shared raise ArgumentError, 'transaction level locks are not supported on MySQL' if transaction # MySQL GET_LOCK supports native timeout: # - timeout_seconds = nil: wait indefinitely (-1) # - timeout_seconds = 0: try once, no wait (0) # - timeout_seconds > 0: wait up to timeout_seconds mysql_timeout = case timeout_seconds when nil then -1 when 0 then 0 else timeout_seconds.to_i end execute_successful?("GET_LOCK(#{quote(lock_keys.first)}, #{mysql_timeout})") end |