Dev build 2026-06-01 21:24
This commit is contained in:
parent
6df47a8161
commit
40c8525691
@ -756,12 +756,39 @@ def _psql_base_args() -> list[str]:
|
||||
]
|
||||
|
||||
|
||||
# Session-GUC SET statements a dump may carry that an OLDER server doesn't know.
|
||||
# These are emitted in the pg_dump header and are harmless to skip — they only
|
||||
# affect the restoring session, not the data. (e.g. `transaction_timeout` was
|
||||
# introduced in PostgreSQL 17; restoring such a dump into a <17 server errors on
|
||||
# that line.) We must not let these abort an otherwise valid restore, but any
|
||||
# OTHER error still fails the restore.
|
||||
_BENIGN_RESTORE_ERROR_MARKERS = (
|
||||
"unrecognized configuration parameter",
|
||||
)
|
||||
|
||||
|
||||
def _real_restore_errors(stderr: str) -> list[str]:
|
||||
errors = []
|
||||
for line in (stderr or "").splitlines():
|
||||
if "ERROR:" not in line:
|
||||
continue
|
||||
if any(marker in line for marker in _BENIGN_RESTORE_ERROR_MARKERS):
|
||||
continue
|
||||
errors.append(line.strip())
|
||||
return errors
|
||||
|
||||
|
||||
def _run_pg_restore(dump_bytes: bytes) -> None:
|
||||
"""Restore a full PostgreSQL dump.
|
||||
|
||||
Resets the public schema first so any plain pg_dump (with or without
|
||||
--clean) restores cleanly into an empty schema. This is destructive: it
|
||||
drops and recreates the entire public schema before applying the dump.
|
||||
|
||||
The dump is applied WITHOUT ON_ERROR_STOP so that benign header SETs the
|
||||
target server doesn't recognize (e.g. a newer pg_dump emitting
|
||||
`transaction_timeout` against an older server) don't abort the restore.
|
||||
stderr is then inspected: any non-benign `ERROR:` line fails the restore.
|
||||
"""
|
||||
env = os.environ.copy()
|
||||
env["PGPASSWORD"] = os.environ.get("POSTGRES_PASSWORD", "")
|
||||
@ -782,13 +809,14 @@ def _run_pg_restore(dump_bytes: bytes) -> None:
|
||||
|
||||
try:
|
||||
proc = subprocess.run(
|
||||
["psql", *base, "-v", "ON_ERROR_STOP=1", "-f", str(tmp_path)],
|
||||
["psql", *base, "-f", str(tmp_path)],
|
||||
env=env,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
if proc.returncode != 0:
|
||||
raise RuntimeError(f"psql restore failed: {(proc.stderr or '').strip()[:500] or 'unknown error'}")
|
||||
real_errors = _real_restore_errors(proc.stderr)
|
||||
if real_errors:
|
||||
raise RuntimeError("psql restore failed: " + " | ".join(real_errors)[:500])
|
||||
finally:
|
||||
tmp_path.unlink(missing_ok=True)
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ from __future__ import annotations
|
||||
|
||||
from changelog import CHANGELOG
|
||||
|
||||
BUILD = 1
|
||||
BUILD = 2
|
||||
|
||||
|
||||
def _release_version() -> str:
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
# Develop Changelog
|
||||
|
||||
## 2026-06-01 — Full Database Restore: tolerate PostgreSQL version mismatch
|
||||
|
||||
### Fixed
|
||||
- Full Database Restore failed with `ERROR: unrecognized configuration parameter "transaction_timeout"` when the dump was produced by a newer `pg_dump` (PostgreSQL 17+, which emits `SET transaction_timeout = 0;` in the header) but restored into an older server (<17) that doesn't know that session parameter. The restore ran with `ON_ERROR_STOP=1` and aborted on that harmless header line.
|
||||
- `routers/backup.py` (`_run_pg_restore`): the dump is now applied without `ON_ERROR_STOP`; stderr is inspected afterwards via `_real_restore_errors`, which ignores benign "unrecognized configuration parameter" errors but still fails the restore on any other `ERROR:` line. The schema-reset step keeps `ON_ERROR_STOP=1` (it is our own controlled SQL).
|
||||
|
||||
## 2026-06-01 — Backup/Restore: database-stored books are now restorable
|
||||
|
||||
### Fixed
|
||||
|
||||
Loading…
Reference in New Issue
Block a user