From dd4874ae8dda36a2246edcd7527ab5ac96b93646 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Sun, 24 May 2026 11:10:04 -0400 Subject: [PATCH] fix: 30min wall-clock timeout on backup subprocess + global padding-top on .fc-content so views don't start under the sticky TopNav Co-Authored-By: Claude Opus 4.7 (1M context) --- backend/app/services/migrators/backup.py | 11 ++++++++++- frontend/src/components/AppShell.vue | 6 ++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/backend/app/services/migrators/backup.py b/backend/app/services/migrators/backup.py index 4d3cb96..d0bbf72 100644 --- a/backend/app/services/migrators/backup.py +++ b/backend/app/services/migrators/backup.py @@ -37,12 +37,21 @@ def _backups_dir(images_root: Path | None = None) -> Path: return p +_DEFAULT_SUBPROCESS_TIMEOUT_S = 30 * 60 # 30 minutes + + def _run_subprocess(cmd: list[str], **kwargs: Any): - # Overridable for tests via monkeypatch. + # Overridable for tests via monkeypatch. Hard wall-clock timeout + # guards against pg_dump / tar / zstd hangs on NFS — without it the + # task pretends to be 'running' forever (operator hit this 2026-05- + # 23 with two backups stuck in MigrationRun). On timeout + # subprocess.run raises TimeoutExpired which the caller surfaces as + # a task error. return subprocess.run( cmd, capture_output=True, check=True, + timeout=_DEFAULT_SUBPROCESS_TIMEOUT_S, **{k: v for k, v in kwargs.items() if not k.startswith("_")}, ) diff --git a/frontend/src/components/AppShell.vue b/frontend/src/components/AppShell.vue index 3546e40..a583526 100644 --- a/frontend/src/components/AppShell.vue +++ b/frontend/src/components/AppShell.vue @@ -18,5 +18,11 @@ const route = useRoute()