mirror of
https://github.com/calibrain/shelfmark.git
synced 2026-11-14 13:08:24 +00:00
fix(startup): the reconcile guard catches the same errors the rest of main.py does (#1540)
The start-up reconcile runs at import, before the coordinator starts, inside a try that named five exception types and left out `TypeError`. `main.py` already defines `_IMPORT_OPERATIONAL_ERRORS` for this shape and the other module-level guards use it, so this switches to it. An unexpected `TypeError` from the reconcile would otherwise fail the import of `shelfmark.main`, and the worker would fail to boot on every restart. I didn't use `except Exception` because BLE001 is on and nothing in main.py does. The test reloads main with the reconcile raising `TypeError`, and with `OSError` as the control (that one already passes on main). Full non-e2e suite passes, ruff and basedpyright are clean. Found in a Claude pass over 1.5.0.
This commit is contained in:
1 parent
f560b31ee4
commit
08fdb7ea87
2 files changed
+40
-1
No files matched your search
+1
-1
@@ -285,7 +285,7 @@ if user_db is not None and download_history_service is not None:
|
||||
_reconciled["marked"],
|
||||
_reconciled["reopened"],
|
||||
)
|
||||
except (ImportError, OSError, RuntimeError, ValueError, sqlite3.Error) as exc:
|
||||
except _IMPORT_OPERATIONAL_ERRORS as exc:
|
||||
logger.warning("Could not reconcile interrupted downloads at startup: %s", exc)
|
||||
|
||||
# Start download coordinator
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
"""A reconcile that cannot run must never stop the app from starting."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from shelfmark.core.logger import CustomLogger
|
||||
|
||||
|
||||
@pytest.mark.parametrize("error", [TypeError("unexpected row shape"), OSError("disk went away")])
|
||||
def test_a_failing_startup_reconcile_only_logs_a_warning(error):
|
||||
"""The module-level guard in main.py runs before the coordinator starts.
|
||||
|
||||
An error it does not catch fails the import of shelfmark.main, and the worker then
|
||||
fails to boot on every restart.
|
||||
"""
|
||||
# Patch the class, not main.logger: reloading main builds a new logger object.
|
||||
with (
|
||||
patch("shelfmark.download.orchestrator.start"),
|
||||
patch("shelfmark.download.warmup.start"),
|
||||
patch(
|
||||
"shelfmark.core.startup_reconcile.reconcile_interrupted_downloads",
|
||||
side_effect=error,
|
||||
) as reconcile,
|
||||
patch.object(CustomLogger, "warning") as warning,
|
||||
):
|
||||
import shelfmark.main as main
|
||||
|
||||
importlib.reload(main)
|
||||
|
||||
# Importing and then reloading runs the module body twice, so only check it was reached.
|
||||
assert reconcile.called
|
||||
assert any(
|
||||
"Could not reconcile interrupted downloads at startup" in str(call.args[0])
|
||||
for call in warning.call_args_list
|
||||
)
|
||||
Reference in new issue
Block a user