Class: Postgresql::ReplicationSlot
- Inherits:
-
Gitlab::Database::SharedModel
- Object
- ActiveRecord::Base
- Gitlab::Database::SharedModel
- Postgresql::ReplicationSlot
- Defined in:
- app/models/postgresql/replication_slot.rb
Class Method Summary collapse
- .count ⇒ Object
-
.in_use? ⇒ Boolean
Returns true if there are any replication slots in use.
-
.lag_too_great?(max = 100.megabytes) ⇒ Boolean
Returns true if the lag observed across all replication slots exceeds a given threshold.
- .max_replication_slots ⇒ Object
-
.max_retained_wal ⇒ Object
returns the max number WAL space (in bytes) being used across the replication slots.
-
.slots_retained_bytes ⇒ Object
array of slots and the retained_bytes www.skillslogic.com/blog/databases/checking-postgres-replication-lag bdr-project.org/docs/stable/monitoring-peers.html.
- .unused_slots_count ⇒ Object
- .used_slots_count ⇒ Object
Methods inherited from Gitlab::Database::SharedModel
connection, #connection_db_config, connection_pool, using_connection
Class Method Details
.count ⇒ Object
43 44 45 46 47 48 49 |
# File 'app/models/postgresql/replication_slot.rb', line 43 def self.count connection .execute("SELECT COUNT(*) FROM pg_replication_slots;") .first .fetch('count') .to_i end |
.in_use? ⇒ Boolean
Returns true if there are any replication slots in use. PostgreSQL-compatible databases such as Aurora don’t support replication slots, so this will return false as well.
10 11 12 13 14 |
# File 'app/models/postgresql/replication_slot.rb', line 10 def self.in_use? transaction { exists? } rescue ActiveRecord::StatementInvalid false end |
.lag_too_great?(max = 100.megabytes) ⇒ Boolean
Returns true if the lag observed across all replication slots exceeds a given threshold.
max - The maximum replication lag size, in bytes. Based on GitLab.com
statistics it takes between 1 and 5 seconds to replicate around
100 MB of data.
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'app/models/postgresql/replication_slot.rb', line 22 def self.lag_too_great?(max = 100.megabytes) return false unless in_use? lag_function = "pg_wal_lsn_diff" \ "(pg_current_wal_insert_lsn(), restart_lsn)::bigint" # We force the use of a transaction here so the query always goes to the # primary, even when using the DB load balancer. sizes = transaction { pluck(Arel.sql(lag_function)) } too_great = sizes.compact.count { |size| size >= max } # If too many replicas are falling behind too much, the availability of a # GitLab instance might suffer. To prevent this from happening we require # at least 1 replica to have data recent enough. if sizes.any? && too_great > 0 (sizes.length - too_great) <= 1 else false end end |
.max_replication_slots ⇒ Object
87 88 89 90 91 |
# File 'app/models/postgresql/replication_slot.rb', line 87 def self.max_replication_slots connection.execute(<<-SQL.squish).first&.fetch('setting').to_i SELECT setting FROM pg_settings WHERE name = 'max_replication_slots'; SQL end |
.max_retained_wal ⇒ Object
returns the max number WAL space (in bytes) being used across the replication slots
80 81 82 83 84 85 |
# File 'app/models/postgresql/replication_slot.rb', line 80 def self.max_retained_wal connection.execute(<<-SQL.squish).first.fetch('coalesce').to_i SELECT COALESCE(MAX(pg_wal_lsn_diff(pg_current_wal_insert_lsn(), restart_lsn)), 0) FROM pg_replication_slots; SQL end |
.slots_retained_bytes ⇒ Object
array of slots and the retained_bytes www.skillslogic.com/blog/databases/checking-postgres-replication-lag bdr-project.org/docs/stable/monitoring-peers.html
70 71 72 73 74 75 76 77 |
# File 'app/models/postgresql/replication_slot.rb', line 70 def self.slots_retained_bytes connection.execute(<<-SQL.squish).to_a SELECT slot_name, database, active, pg_wal_lsn_diff(pg_current_wal_insert_lsn(), restart_lsn) AS retained_bytes FROM pg_replication_slots; SQL end |
.unused_slots_count ⇒ Object
51 52 53 54 55 56 57 |
# File 'app/models/postgresql/replication_slot.rb', line 51 def self.unused_slots_count connection .execute("SELECT COUNT(*) FROM pg_replication_slots WHERE active = 'f';") .first .fetch('count') .to_i end |
.used_slots_count ⇒ Object
59 60 61 62 63 64 65 |
# File 'app/models/postgresql/replication_slot.rb', line 59 def self.used_slots_count connection .execute("SELECT COUNT(*) FROM pg_replication_slots WHERE active = 't';") .first .fetch('count') .to_i end |