gitlab-org--gitlab-foss/app/models/postgresql/replication_slot.rb
Stan Hu fd7f95ee74 Disable replication lag check for Aurora PostgreSQL databases
Replication slots are not supported in Aurora. Attempting to check
the lag results in the message:

```
ActiveRecord::StatementInvalid: PG::FeatureNotSupported: ERROR:
Replication slots are currently not supported in Aurora : SELECT
pg_xlog_location_diff(pg_current_xlog_insert_location(),
restart_lsn)::...
```

To avoid breaking support for background migrations in Aurora, we just
disable the check if we encounter this error.

This change also now checks whether there are any replication slots
present in the primary before checking the replication lag.

Closes https://gitlab.com/gitlab-org/gitlab-ce/issues/52176
2018-11-03 07:00:31 -07:00

43 lines
1.5 KiB
Ruby

# frozen_string_literal: true
module Postgresql
class ReplicationSlot < ActiveRecord::Base
self.table_name = 'pg_replication_slots'
# 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.
def self.in_use?
transaction { exists? }
rescue ActiveRecord::StatementInvalid
false
end
# 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.
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.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.positive?
(sizes.length - too_great) <= 1
else
false
end
end
end
end