Module: ResilientReads::LagChecker
- Defined in:
- lib/resilient_reads/lag_checker.rb
Class Method Summary collapse
-
.lag_for(replica) ⇒ Object
Returns the replication lag in seconds for a replica.
- .lag_for_mysql(conn) ⇒ Object
- .lag_for_postgresql(conn) ⇒ Object
-
.replication_lag ⇒ Object
Convenience: check replication lag using the default reading connection.
Class Method Details
.lag_for(replica) ⇒ Object
Returns the replication lag in seconds for a replica. Supports PostgreSQL and MySQL/MariaDB. Returns 0 when the replica is fully caught up, nil on error.
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'lib/resilient_reads/lag_checker.rb', line 6 def self.lag_for(replica) conn = replica.connection adapter_name = conn.adapter_name.downcase if adapter_name.include?("postgresql") lag_for_postgresql(conn) elsif adapter_name.include?("mysql") || adapter_name.include?("trilogy") lag_for_mysql(conn) else ResilientReads.log(:debug, "Lag check not supported for adapter '#{adapter_name}'") nil end rescue => e ResilientReads.log(:debug, "Lag check failed for '#{replica.name}': #{e.}") nil ensure replica.release_connection rescue nil end |
.lag_for_mysql(conn) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/resilient_reads/lag_checker.rb', line 47 def self.lag_for_mysql(conn) # Prefer SHOW REPLICA STATUS (MySQL 8.0.22+, MariaDB 10.5.1+) # and fall back to the deprecated SHOW SLAVE STATUS. ResilientReads.log(:debug, "MySQL Replica Lag Start") lag = begin result = conn.execute("SHOW REPLICA STATUS") if result.present? && result.rows.present? result.rows.first[result.fields.index("Seconds_Behind_Source")] else nil end rescue ActiveRecord::StatementInvalid result = conn.execute("SHOW SLAVE STATUS") if result.present? && result.rows.present? result.rows.first[result.fields.index("Seconds_Behind_Master")] else nil end end ResilientReads.log(:debug, "MySQL Replica Lag: #{lag}") lag&.to_f rescue => e ResilientReads.log(:debug, "MySQL lag check failed: #{e.}") nil end |
.lag_for_postgresql(conn) ⇒ Object
35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/resilient_reads/lag_checker.rb', line 35 def self.lag_for_postgresql(conn) result = conn.execute(<<~SQL) SELECT CASE WHEN pg_last_wal_receive_lsn() IS NULL THEN NULL WHEN pg_last_wal_receive_lsn() = pg_last_wal_replay_lsn() THEN 0 ELSE EXTRACT(EPOCH FROM now() - pg_last_xact_replay_timestamp())::float END AS lag SQL lag = result.first&.fetch("lag", nil) lag&.to_f end |
.replication_lag ⇒ Object
Convenience: check replication lag using the default reading connection.
26 27 28 29 30 31 |
# File 'lib/resilient_reads/lag_checker.rb', line 26 def self.replication_lag replica = ResilientReads.replica_pool.next_healthy return nil unless replica lag_for(replica) end |