Module: ActiveRecordPostgresRecovery::Handler

Defined in:
lib/active_record_postgres_recovery/handler.rb

Constant Summary collapse

DB_CONNECTIVITY_ERROR_CLASSES =
[PG::ConnectionBad, ActiveRecord::ConnectionNotEstablished].freeze
READ_ONLY_TRANSACTION_MESSAGE =
/read-only transaction/i
RECOVERY_REPORTED_IVAR =
:@active_record_postgres_recovery_reported

Class Method Summary collapse

Class Method Details

.clear_active_connections!Object



19
20
21
22
23
24
# File 'lib/active_record_postgres_recovery/handler.rb', line 19

def clear_active_connections!
  roles = ActiveRecordPostgresRecovery.configuration.roles
  handler = ActiveRecord::Base.connection_handler
  roles.each { |role| handler.clear_active_connections!(role) }
  build_clear_action(strategy: 'active', performed: true, roles: roles)
end

.clear_all_connections!(roles: ActiveRecordPostgresRecovery.configuration.roles) ⇒ Object



26
27
28
29
30
# File 'lib/active_record_postgres_recovery/handler.rb', line 26

def clear_all_connections!(roles: ActiveRecordPostgresRecovery.configuration.roles)
  handler = ActiveRecord::Base.connection_handler
  roles.each { |role| handler.clear_all_connections!(role) }
  build_clear_action(strategy: 'all', performed: true, roles: roles)
end

.clear_failover_connections!Object



32
33
34
35
36
37
# File 'lib/active_record_postgres_recovery/handler.rb', line 32

def clear_failover_connections!
  roles = ActiveRecordPostgresRecovery.configuration.failover_clear_roles
  build_clear_action(strategy: 'failover_all', performed: true, roles: roles).tap do
    clear_all_connections!(roles: roles)
  end
end

.db_connectivity_error?(error) ⇒ Boolean

Returns:

  • (Boolean)


15
16
17
# File 'lib/active_record_postgres_recovery/handler.rb', line 15

def db_connectivity_error?(error)
  !matching_error(error).nil?
end

.read_only_transaction_error?(error) ⇒ Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/active_record_postgres_recovery/handler.rb', line 39

def read_only_transaction_error?(error)
  !find_error_in_chain(error) { |current| current.message.to_s.match?(READ_ONLY_TRANSACTION_MESSAGE) }.nil?
end

.report_attempted_recovery(context:, error:, source:, retrying: false, clear_action: nil) ⇒ Object



43
44
45
# File 'lib/active_record_postgres_recovery/handler.rb', line 43

def report_attempted_recovery(context:, error:, source:, retrying: false, clear_action: nil)
  report_recovery(context: context, error: error, source: source, outcome: :attempted, retrying: retrying, clear_action: clear_action)
end

.report_recovery(context:, error:, source:, outcome:, retrying: false, clear_action: nil) ⇒ Object



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/active_record_postgres_recovery/handler.rb', line 51

def report_recovery(context:, error:, source:, outcome:, retrying: false, clear_action: nil)
  return if recovery_reported?(error)

  matched_error = matching_error(error) || error
  clear_action ||= build_clear_action(strategy: nil, performed: false, roles: [])

  ActiveRecordPostgresRecovery.report(
    RecoveryEvent.new(
      outcome: outcome,
      source: source,
      context: context,
      error: error,
      matched_error: matched_error,
      retrying: retrying,
      clear_action: clear_action
    )
  )

  mark_recovery_reported!(error)
end

.report_successful_recovery(context:, error:, source:, clear_action: nil) ⇒ Object



47
48
49
# File 'lib/active_record_postgres_recovery/handler.rb', line 47

def report_successful_recovery(context:, error:, source:, clear_action: nil)
  report_recovery(context: context, error: error, source: source, outcome: :recovered, retrying: true, clear_action: clear_action)
end