#!/usr/bin/env bash
# Siklus hidup replication slot: dibuat oleh pg_basebackup -C, menjaga WAL
# selama standby mati, lalu dihapus saat tidak lagi dibutuhkan.
# Server mini: primary port 54345, standby port 54346, database toko.
# Skrip ini mandiri: membersihkan dirinya sendiri di akhir.
set -eu

PGBIN=/home/z/my-project/tools/dl/pgdeb/usr/lib/postgresql/17/bin
BASE=/home/z/my-project/tmp/rp_slot
PRI=$BASE/pgdata_pusat     # primary, port 54345
STD=$BASE/pgdata_cabang    # standby,  port 54346
SOCK=$BASE/sock

bersihkan() {
  "$PGBIN/pg_ctl" -D "$PRI" -m immediate stop >/dev/null 2>&1 || true
  "$PGBIN/pg_ctl" -D "$STD" -m immediate stop >/dev/null 2>&1 || true
  rm -rf "$BASE"
}
trap bersihkan EXIT

# Buang sisa percobaan sebelumnya bila ada.
bersihkan
mkdir -p "$SOCK"

# Polling: tunggu sampai sebuah query mengembalikan nilai yang diharapkan.
tunggu() {  # port database sql nilai_yang_diharapkan
  local port="$1" db="$2" sql="$3" harapan="$4" i hasil
  for i in $(seq 1 80); do
    hasil=$(psql -X -q -t -A -h 127.0.0.1 -p "$port" -U postgres -d "$db" \
            -c "$sql" 2>/dev/null) || true
    if [ "$hasil" = "$harapan" ]; then return 0; fi
    sleep 0.2
  done
  echo "TIMEOUT: menunggu '$sql' menjadi $harapan (port $port)" >&2
  return 1
}

echo "== Langkah 1: initdb dan jalankan primary di port 54345 =="
"$PGBIN/initdb" -D "$PRI" --no-locale -E UTF8 -U postgres >/dev/null 2>&1
"$PGBIN/pg_ctl" -D "$PRI" \
  -o "-p 54345 -k $SOCK -c listen_addresses=127.0.0.1" \
  -l "$BASE/primary.log" start >/dev/null 2>&1
tunggu 54345 postgres "SELECT 1;" "1"
psql -X -h 127.0.0.1 -p 54345 -U postgres -d postgres \
  -c "CREATE DATABASE toko;"
psql -X -h 127.0.0.1 -p 54345 -U postgres -d toko \
  -c "CREATE TABLE produk (id int PRIMARY KEY, nama text, harga numeric);" \
  -c "INSERT INTO produk VALUES (1, 'Kopi Tubruk', 15000), (2, 'Teh Celup', 8000);"

echo "== Langkah 2: base backup dengan slot (-C -S slot_cabang -R) =="
PGDATABASE=postgres pg_basebackup -h 127.0.0.1 -p 54345 -U postgres \
  -D "$STD" -R -X stream -c fast -C -S slot_cabang >/dev/null 2>&1
psql -X -h 127.0.0.1 -p 54345 -U postgres -d postgres \
  -c "SELECT slot_name, slot_type, active, wal_status FROM pg_replication_slots;"
grep primary_slot_name "$STD/postgresql.auto.conf"

echo "== Langkah 3: jalankan standby dan pastikan data mengalir =="
"$PGBIN/pg_ctl" -D "$STD" \
  -o "-p 54346 -k $SOCK -c listen_addresses=127.0.0.1 -c cluster_name=standby_cabang" \
  -l "$BASE/standby.log" start >/dev/null 2>&1
tunggu 54346 toko "SELECT count(*) FROM produk;" "2"
psql -X -h 127.0.0.1 -p 54345 -U postgres -d toko \
  -c "INSERT INTO produk VALUES (3, 'Gula Pasir', 12000);"
tunggu 54346 toko "SELECT count(*) FROM produk;" "3"
psql -X -h 127.0.0.1 -p 54345 -U postgres -d postgres \
  -c "SELECT slot_name, slot_type, active, wal_status FROM pg_replication_slots;"

echo "== Langkah 4: matikan standby, lalu terus menulis di primary =="
"$PGBIN/pg_ctl" -D "$STD" -m fast stop >/dev/null 2>&1
psql -X -h 127.0.0.1 -p 54345 -U postgres -d toko \
  -c "INSERT INTO produk VALUES (4, 'Susu Kental', 9000), (5, 'Keju Slice', 21000);"
psql -X -h 127.0.0.1 -p 54345 -U postgres -d postgres \
  -c "SELECT slot_name, slot_type, active, wal_status FROM pg_replication_slots;"

echo "== Langkah 5: nyalakan standby lagi — WAL yang dipertahankan slot menyelamatkannya =="
"$PGBIN/pg_ctl" -D "$STD" \
  -o "-p 54346 -k $SOCK -c listen_addresses=127.0.0.1 -c cluster_name=standby_cabang" \
  -l "$BASE/standby.log" start >/dev/null 2>&1
tunggu 54346 toko "SELECT count(*) FROM produk;" "5"
psql -X -h 127.0.0.1 -p 54346 -U postgres -d toko \
  -c "SELECT id, nama, harga FROM produk ORDER BY id;"

echo "== Langkah 6: slot tidak dipakai lagi — hapus agar WAL bebas terdaur =="
"$PGBIN/pg_ctl" -D "$STD" -m fast stop >/dev/null 2>&1
psql -X -h 127.0.0.1 -p 54345 -U postgres -d postgres \
  -c "SELECT pg_drop_replication_slot('slot_cabang');" \
  -c "SELECT count(*) AS sisa_slot FROM pg_replication_slots;"
