diff --git a/docs/review/remote_pull_and_mirror_operability_2026-08-04.md b/docs/review/remote_pull_and_mirror_operability_2026-08-04.md index 0a2bd2e..719db7e 100644 --- a/docs/review/remote_pull_and_mirror_operability_2026-08-04.md +++ b/docs/review/remote_pull_and_mirror_operability_2026-08-04.md @@ -1,6 +1,6 @@ # Review: `remote pull`, and what a mirror operator cannot see -Status: **open** — F1 and F5 released in v5.6.0; F2, F3, F4, F6 outstanding +Status: **open** — F1 and F5 released in v5.6.0; F2, F3, F4, F6 outstanding; **F7 added 2026-08-06, fixed locally and awaiting release** Author: claude (Opus 5), 2026-08-04 Scope: `owilix/core/tasks/remote.py`, `owilix/http_api/server.py`, packaging Source of evidence: the OpenWebSearch.eu `ourrs` clusters (owilix **5.5.1** @@ -145,6 +145,45 @@ LEXIS zones rather than one source. --- +## F7 — `remote doctor` raises TypeError for every non-LEXIS repository + +**Severity: high for anyone with a non-LEXIS remote. Fixed locally, not +released.** + +``` +owi-up: {"error": "TypeError: FileBasedRepository.status() got an unexpected + keyword argument 'progress_cb'"} +``` + +Reproduced on both OpenWebSearch.eu clusters against 5.6.0, via +`POST /remote/doctor/status`. LEXIS reports fully — per-access-level `ok`, +dataset counts and zones (`public` 1852 across `IT4ILexisV2`/`OWILRZZONE`) — +while the s3a mirror reports only this error. + +`core/tasks/remote.py:504` calls `repo.status(progress_cb=progress_cb)` +unconditionally. `LexisRepository.status` grew the parameter; +`BaseRepository.status`, `FileBasedRepository.status` and +`AggregateRepository.status` did not. So the callback was added to the caller +and to one implementation, and every other backend now raises on a call that +looks routine. + +It matters more than a signature slip suggests: **file-based is every non-LEXIS +repository**, which is precisely the class OWILIX is valuable for holding — the +argument for OWILIX being authoritative for contents is that it can hold +repositories LEXIS cannot. A doctor that cannot report on them undercuts that. + +*Fixed here:* `progress_cb=None` accepted and ignored on the base and +file-based implementations, forwarded by the aggregate. Accepting and ignoring +is the right default for a backend whose status is a local existence check with +no progress worth reporting. + +Consumer note: until a release carries this, a dashboard cannot show a health +light for an s3a mirror from `doctor` at all, and should say the backend is not +probeable rather than render it as unhealthy — an error from the prober is not +a statement about the repository. + +--- + ## F6 — Smaller things - **Two bare `except:`** clauses in `core/tasks/remote.py` swallow diff --git a/owilix/core/repository/aggregate.py b/owilix/core/repository/aggregate.py index 5be42ac..851c5c2 100644 --- a/owilix/core/repository/aggregate.py +++ b/owilix/core/repository/aggregate.py @@ -58,8 +58,8 @@ class AggregatedRepository: else: raise NotImplementedError(f"Repository for scheme {parsed.scheme} not implemented") - def status(self) -> Dict[str, dict]: - return {k: r.status() for k, r in self.repositories.items()} + def status(self, progress_cb=None) -> Dict[str, dict]: + return {k: r.status(progress_cb=progress_cb) for k, r in self.repositories.items()} def get_repo_names(self) -> set: return set(self.repositories.keys()) diff --git a/owilix/core/repository/base.py b/owilix/core/repository/base.py index 96408d6..61fbb48 100644 --- a/owilix/core/repository/base.py +++ b/owilix/core/repository/base.py @@ -175,7 +175,17 @@ class AbstractRepository(ABC): }) return _d - def status(self) -> dict: + def status(self, progress_cb=None) -> dict: + """Repository health. + + ``progress_cb`` is part of the contract, not an extra some + implementations happen to take: ``remote doctor`` calls + ``repo.status(progress_cb=...)`` unconditionally, so an implementation + without it raises TypeError and the repository reports as an error + rather than as a status. Accepting and ignoring it is the correct + default for a backend with nothing slow to report. + """ + del progress_cb return self._add_details_to_status({ "status": False, "message": "not implemented", diff --git a/owilix/core/repository/file.py b/owilix/core/repository/file.py index f979ee2..a75ee98 100644 --- a/owilix/core/repository/file.py +++ b/owilix/core/repository/file.py @@ -122,7 +122,12 @@ class FileBasedRepository(AbstractRepository): def __str__(self): return f"{self.__class__.__name__}@{self._filesystem}/{self.path}<{'async+' if self._filesystem_async is not None else 'async-'}>" - def status(self) -> dict: + def status(self, progress_cb=None) -> dict: + # Accepted and ignored: existence checks here are local or a single + # object-store HEAD, so there is no progress worth reporting. Omitting + # it made `remote doctor` raise TypeError for every file-based + # repository -- which is every non-LEXIS one, including the s3a mirror. + del progress_cb try: public_exists = any(self.fs.exists(p) for p in self._get_collection_paths("public")) project_exists = any(self.fs.exists(p) for p in self._get_collection_paths("project"))