# Sourced by managed-container; uses the shared OCF and parameter environment. pg_remote_query() { local sql="$1" pg_replication_exec \ psql \ "host=${REJOIN_SOURCE_HOST} port=${REJOIN_SOURCE_PORT} dbname=postgres user=${REPLICATION_USER}" \ -Atqc "${sql}" } ensure_local_ha_slots() { local slots raw_slot slot slot_type # # POSTGRES_HA_SLOTS lives in the container environment supplied by # postgres.env. It is the cluster-wide list of physical slots that # every writable primary must provide. # slots="$( pg_command ' printf "%s" "${POSTGRES_HA_SLOTS:-}" ' 2>/dev/null )" || { ocf_exit_reason \ "Unable to read POSTGRES_HA_SLOTS from PostgreSQL container" return "${OCF_ERR_GENERIC}" } if [ -z "${slots}" ]; then ocf_log warn \ "POSTGRES_HA_SLOTS is empty; no local HA slots will be reconciled" return "${OCF_SUCCESS}" fi while IFS= read -r raw_slot; do slot="$(printf '%s' "${raw_slot}" | tr -d '[:space:]')" [ -n "${slot}" ] || continue case "${slot}" in *[!a-z0-9_]*) ocf_exit_reason \ "Invalid physical replication slot name: ${slot}" return "${OCF_ERR_CONFIGURED}" ;; esac slot_type="$( pg_command " psql \ -U '${DB_USER}' \ -d postgres \ -At \ -v ON_ERROR_STOP=1 \ -c \" SELECT slot_type FROM pg_replication_slots WHERE slot_name = '${slot}'; \" " 2>/dev/null )" || { ocf_exit_reason \ "Failed querying replication slot ${slot}" return "${OCF_ERR_GENERIC}" } slot_type="$(printf '%s' "${slot_type}" | tr -d '[:space:]')" case "${slot_type}" in physical) ocf_log info \ "Physical HA slot already exists: ${slot}" ;; "") ocf_log info \ "Creating physical HA slot: ${slot}" if ! pg_command " psql \ -U '${DB_USER}' \ -d postgres \ -v ON_ERROR_STOP=1 \ -c \" SELECT pg_create_physical_replication_slot('${slot}'); \" " >/dev/null then ocf_exit_reason \ "Failed creating physical replication slot ${slot}" return "${OCF_ERR_GENERIC}" fi ;; *) ocf_exit_reason \ "Replication slot ${slot} exists but is type ${slot_type}" return "${OCF_ERR_CONFIGURED}" ;; esac done </dev/null )" || return 1 case "${result}" in physical) return 0 ;; "") if ! pg_replication_exec \ psql \ "host=${host} port=${REJOIN_SOURCE_PORT} user=${REPLICATION_USER} dbname=postgres" \ -Atc " SELECT slot_name FROM pg_create_physical_replication_slot('${slot}'); " >/dev/null then return 1 fi return 0 ;; *) ocf_log err \ "Replication slot ${slot} exists on ${host} but is not physical" return 1 ;; esac } candidate_caught_up() { local candidate="${1:-}" local result [ -n "${candidate}" ] || return 1 result="$(pg_command " psql -U '${DB_USER}' -d '${DB_NAME}' -Atc \" SELECT CASE WHEN state = 'streaming' AND replay_lsn >= pg_current_wal_flush_lsn() THEN 'yes' ELSE 'no' END FROM pg_stat_replication WHERE application_name = '${candidate}' LIMIT 1; \" " 2>/dev/null)" || return 1 [ "${result}" = "yes" ] } candidate_is_standby() { local host="${1:-}" local result local port="${REJOIN_SOURCE_PORT:-5432}" [ -n "${host}" ] || return 1 result="$( pg_replication_exec \ psql \ "host=${host} port=${port} user=${REPLICATION_USER} dbname=postgres" \ -Atc "SELECT pg_is_in_recovery();" \ 2>/dev/null )" || return 1 [ "${result}" = "t" ] }