module SafePgMigrations::BlockingActivityLogger
Constants
- FILTERED_COLUMNS
- VERBOSE_COLUMNS
Private Instance Methods
format_start_time(start_time, reference_time = Time.now)
click to toggle source
# File lib/safe-pg-migrations/plugins/blocking_activity_logger.rb, line 115 def format_start_time(start_time, reference_time = Time.now) duration = (reference_time - start_time).round "transaction started #{duration} #{'second'.pluralize(duration)} ago" end
log_blocking_queries() { || ... }
click to toggle source
# File lib/safe-pg-migrations/plugins/blocking_activity_logger.rb, line 55 def log_blocking_queries delay_before_logging = SafePgMigrations.config.safe_timeout - SafePgMigrations.config.blocking_activity_logger_margin blocking_queries_retriever_thread = Thread.new do sleep delay_before_logging SafePgMigrations.alternate_connection.query(select_blocking_queries_sql % raw_connection.backend_pid) end yield blocking_queries_retriever_thread.kill rescue ActiveRecord::LockWaitTimeout SafePgMigrations.say 'Lock timeout.', true queries = begin blocking_queries_retriever_thread.value rescue StandardError => e SafePgMigrations.say("Error while retrieving blocking queries: #{e}", true) nil end raise if queries.nil? if queries.empty? SafePgMigrations.say 'Could not find any blocking query.', true else SafePgMigrations.say( "Statement was being blocked by the following #{'query'.pluralize(queries.size)}:", true ) SafePgMigrations.say '', true output_blocking_queries(queries) SafePgMigrations.say( 'Beware, some of those queries might run in a transaction. In this case the locking query might be '\ 'located elsewhere in the transaction', true ) SafePgMigrations.say '', true end raise end
output_blocking_queries(queries)
click to toggle source
# File lib/safe-pg-migrations/plugins/blocking_activity_logger.rb, line 99 def output_blocking_queries(queries) if SafePgMigrations.config.blocking_activity_logger_verbose queries.each { |query, start_time| SafePgMigrations.say "#{format_start_time start_time}: #{query}", true } else queries.each do |start_time, locktype, mode, pid, transactionid| SafePgMigrations.say( "#{format_start_time(start_time)}: lock type: #{locktype || 'null'}, " \ "lock mode: #{mode || 'null'}, " \ "lock pid: #{pid || 'null'}, " \ "lock transactionid: #{transactionid || 'null'}", true ) end end end
select_blocking_queries_sql()
click to toggle source
# File lib/safe-pg-migrations/plugins/blocking_activity_logger.rb, line 29 def select_blocking_queries_sql columns = SafePgMigrations.config.blocking_activity_logger_verbose ? VERBOSE_COLUMNS : FILTERED_COLUMNS <<~SQL.squish SELECT #{columns.join(', ')} FROM pg_catalog.pg_locks blocked_locks JOIN pg_catalog.pg_stat_activity blocked_activity ON blocked_activity.pid = blocked_locks.pid JOIN pg_catalog.pg_locks blocking_locks ON blocking_locks.locktype = blocked_locks.locktype AND blocking_locks.DATABASE IS NOT DISTINCT FROM blocked_locks.DATABASE AND blocking_locks.relation IS NOT DISTINCT FROM blocked_locks.relation AND blocking_locks.page IS NOT DISTINCT FROM blocked_locks.page AND blocking_locks.tuple IS NOT DISTINCT FROM blocked_locks.tuple AND blocking_locks.virtualxid IS NOT DISTINCT FROM blocked_locks.virtualxid AND blocking_locks.transactionid IS NOT DISTINCT FROM blocked_locks.transactionid AND blocking_locks.classid IS NOT DISTINCT FROM blocked_locks.classid AND blocking_locks.objid IS NOT DISTINCT FROM blocked_locks.objid AND blocking_locks.objsubid IS NOT DISTINCT FROM blocked_locks.objsubid AND blocking_locks.pid != blocked_locks.pid JOIN pg_catalog.pg_stat_activity blocking_activity ON blocking_activity.pid = blocking_locks.pid WHERE blocked_locks.pid = %d SQL end