# Semana 16: particionamiento, replicación y two-phase commit.
# Se usa dentro del contenedor del curso.
#
#   make              crea la base de datos chasqui_w16 con los datos de ejemplo
#                     y las tablas particionadas de partitions.sql
#   make cluster      crea y arranca un cluster desechable de PostgreSQL
#                     (primario en el puerto 5416, réplica en el 5417, sockets
#                     en /tmp), con max_prepared_transactions = 10 y las bases
#                     de twopc-setup.sql
#   make test         chasqui_w16 y el cluster de nuevo, las pruebas
#                     (*.test.mjs) y al final borra el cluster
#   make cluster-rm   detiene y borra el cluster desechable
#   make clean        borra chasqui_w16 y el cluster
#
# El cluster desechable existe porque el servidor del curso tiene
# max_prepared_transactions = 0 y no hay que reiniciarlo ni configurarlo
# para una demostración. Conéctense a él con
#   psql -h /tmp -p 5416 -U postgres -d sur
#
# initdb y pg_ctl no corren como root: si la shell es de root, se usa gosu.

DB = chasqui_w16
PSQL = psql -X -q -v ON_ERROR_STOP=1

PRIMARY = /tmp/w16-primary
REPLICA = /tmp/w16-replica
PRIMARY_PORT = 5416
REPLICA_PORT = 5417
AS_PG = $(if $(filter 0,$(shell id -u)),gosu postgres,)
OPTS = -k /tmp -c listen_addresses= -c max_prepared_transactions=10

.PHONY: all cluster cluster-rm test clean

all:
	chasqui-load $(DB)
	$(PSQL) -d $(DB) -f partitions.sql

cluster: cluster-rm
	$(AS_PG) initdb -D $(PRIMARY) -A trust -U postgres >/dev/null
	$(AS_PG) pg_ctl -D $(PRIMARY) -l $(PRIMARY).log -w -s \
	  -o "-p $(PRIMARY_PORT) $(OPTS) -c cluster_name=primary" start
	$(PSQL) -h /tmp -p $(PRIMARY_PORT) -U postgres -d postgres -f twopc-setup.sql
	$(AS_PG) pg_basebackup -h /tmp -p $(PRIMARY_PORT) -U postgres \
	  -D $(REPLICA) -R -X stream -c fast
	$(AS_PG) pg_ctl -D $(REPLICA) -l $(REPLICA).log -w -s \
	  -o "-p $(REPLICA_PORT) $(OPTS) -c cluster_name=replica1" start
	@echo "Cluster listo: primario en el puerto $(PRIMARY_PORT), réplica en el $(REPLICA_PORT)."

cluster-rm:
	-@[ -f $(REPLICA)/postmaster.pid ] && $(AS_PG) pg_ctl -D $(REPLICA) -m immediate -w -s stop || true
	-@[ -f $(PRIMARY)/postmaster.pid ] && $(AS_PG) pg_ctl -D $(PRIMARY) -m immediate -w -s stop || true
	rm -rf $(PRIMARY) $(REPLICA) $(PRIMARY).log $(REPLICA).log

# Las pruebas cambian datos y detienen la réplica: una después de otra. El
# cluster se borra aunque alguna prueba falle.
test: all cluster
	PGDATABASE=$(DB) node --test --test-concurrency=1 --test-reporter=spec; \
	  status=$$?; $(MAKE) -s cluster-rm; exit $$status

clean: cluster-rm
	dropdb --if-exists $(DB)
