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 |
# File 'lib/resilient_reads/lag_checker.rb', line 47 def self.lag_for_mysql(conn) result = conn.execute("SHOW SLAVE STATUS") # MySQL 8.0.22+ uses SHOW REPLICA STATUS result = conn.execute("SHOW REPLICA STATUS") if result.respond_to?(:count) && result.count == 0 row = if result.respond_to?(:first) result.first elsif result.respond_to?(:to_a) result.to_a.first end return nil unless row # Seconds_Behind_Master / Seconds_Behind_Source (MySQL 8.0.22+) lag = if row.is_a?(Hash) row["Seconds_Behind_Master"] || row["Seconds_Behind_Source"] elsif row.respond_to?(:[]) row["Seconds_Behind_Master"] || row["Seconds_Behind_Source"] end 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 |