From ebe5fce07bd9ceaf3a247ee21d2e0dddb3b697cb Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Tue, 25 Aug 2026 10:39:19 +0000 Subject: [PATCH] fix: drop the bootstrapped windmill database before the restore POSTGRES_DB creates an empty windmill database, so the dump's own CREATE DATABASE for it fails and its objects load into the entrypoint's database instead, keeping the new cluster's encoding and collation rather than the dumped ones. Sibling databases are created by the dump and so were never affected. Dropping it first makes the restore reproduce the source cluster exactly, and leaves one expected error instead of two. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Ha6ovKdT9XRoj5FyVe7fEt --- docker-compose.yml | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index a4bee100fe..2ef67800fa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -27,19 +27,23 @@ services: ## docker volume ls | grep db_data # then remove the one this project owns ## docker volume rm ## docker compose up --wait db + ## docker compose exec -T db psql -U postgres -d postgres -c 'DROP DATABASE windmill' ## docker compose exec -T db psql -U postgres -d postgres < cluster.sql > restore.log 2>&1 - ## grep -i '^ERROR' restore.log # only the two expected ones, see below + ## grep -i '^ERROR' restore.log # only `role "postgres" already exists` ## docker compose exec -T db vacuumdb -U postgres --all --analyze-in-stages ## docker compose up -d - ## `up --wait` because psql would otherwise race initdb on a fresh volume. psql - ## does not stop on error and the old volume is already gone by then, so grep the - ## log rather than trust its exit code; `database "windmill" already exists` and - ## `role "postgres" already exists` are the two the fresh cluster causes itself. - ## vacuumdb spans every restored database, which a plain ANALYZE would not: each - ## comes back with no planner statistics, and a fork database is where the stall - ## shows. Postgres triggers reading a database in this cluster come back disabled - ## with "replication slot ... no longer exists", since slots are never dumped; - ## re-saving the trigger recreates the slot. + ## `up --wait` because psql would otherwise race initdb on a fresh volume. The + ## DROP is what lets the dump's own `CREATE DATABASE windmill` run: POSTGRES_DB + ## has already made an empty one, and loading into it would keep the new cluster's + ## encoding and collation instead of the dumped ones, for that database only. + ## psql does not stop on error and the old volume is already gone by then, so grep + ## the log rather than trust its exit code; the fresh cluster bootstraps `postgres` + ## itself, so that role is the one error left. vacuumdb spans every restored + ## database, which a plain ANALYZE would not: each comes back with no planner + ## statistics, and a fork database is where the stall shows. Postgres triggers + ## reading a database in this cluster come back disabled with "replication slot + ## ... no longer exists", since slots are never dumped; re-saving the trigger + ## recreates the slot, then re-enable it. db: deploy: # To use an external database, set replicas to 0 and set DATABASE_URL to the external database url in the .env file