From cc88fd8aac1bdaa1ba95412cb585f29068a04acb Mon Sep 17 00:00:00 2001 From: Ruben Fiszel Date: Tue, 25 Aug 2026 10:19:48 +0000 Subject: [PATCH] fix: analyze every restored database and check the restore for errors ANALYZE is per-database, so the sibling datatable/DuckLake/wm_fork_* databases the recipe now restores were left with no planner statistics; vacuumdb --all covers them. psql does not stop on error and the old volume is gone by that point, so the restore needs an explicit grep rather than a trusted exit code. Also note that logical replication slots are never dumped, so a Postgres trigger reading a database in this cluster comes back disabled until it is re-saved. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Ha6ovKdT9XRoj5FyVe7fEt --- docker-compose.yml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 63e05d1c7c..a4bee100fe 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -27,15 +27,19 @@ 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 < cluster.sql - ## docker compose exec -T db psql -U postgres -d windmill -c ANALYZE + ## 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 + ## docker compose exec -T db vacuumdb -U postgres --all --analyze-in-stages ## docker compose up -d - ## `database "windmill" already exists` and `role "postgres" already exists` are - ## expected; the fresh cluster bootstraps both, and psql carries on to load into - ## them. ANALYZE is not optional: a restored cluster starts with no planner - ## statistics, which reads as "the upgrade made Windmill slow" until autovacuum - ## catches up. `up --wait` rather than `up -d` because psql would otherwise race - ## initdb on a fresh volume. + ## `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. db: deploy: # To use an external database, set replicas to 0 and set DATABASE_URL to the external database url in the .env file