Class: Postgresql::ReplicationSlot

Inherits:
ApplicationRecord show all
Defined in:
app/models/postgresql/replication_slot.rb

Class Method Summary collapse

Methods inherited from ApplicationRecord

at_most, id_in, id_not_in, iid_in, pluck_primary_key, primary_key_in, safe_ensure_unique, safe_find_or_create_by, safe_find_or_create_by!, underscore, without_order

Class Method Details

.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.

Returns:

  • (Boolean)

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.

Returns:

  • (Boolean)

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 = "#{Gitlab::Database.pg_wal_lsn_diff}" \
    "(#{Gitlab::Database.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 EE DB load balancer.
  sizes = transaction { pluck(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