From bee67e736a0f9ec1d6a334320fca5629e1af3101 Mon Sep 17 00:00:00 2001 From: Yiorgis Gozadinos Date: Fri, 28 Aug 2026 09:11:30 +0300 Subject: [PATCH] Say what a federated client owns, and trim four comments The set shares the reranker its facades borrow, not an embedder: each covered database builds and closes its own. Sharing one needs the lender pattern inside `Store`, since a store's embedder also serves writes and is closed with the session, so it is left as follow-up rather than done here. `reported_location` returned `client.location` and nothing else; its test asserted that a mock returns what it was given. `list_documents` names its results through `name_all`. --- haiku_rag_slim/haiku/rag/cli.py | 2 +- haiku_rag_slim/haiku/rag/client/__init__.py | 5 +++-- haiku_rag_slim/haiku/rag/client/session.py | 12 +++++++----- .../haiku/rag/ingester/api/routes/database.py | 2 -- .../haiku/rag/inspector/widgets/info_modal.py | 18 +++--------------- tests/test_inspector.py | 8 -------- 6 files changed, 14 insertions(+), 33 deletions(-) diff --git a/haiku_rag_slim/haiku/rag/cli.py b/haiku_rag_slim/haiku/rag/cli.py index a5e2324c..36c8124b 100644 --- a/haiku_rag_slim/haiku/rag/cli.py +++ b/haiku_rag_slim/haiku/rag/cli.py @@ -460,7 +460,7 @@ def settings(): from haiku.rag.app import HaikuRAGApp config = get_config() - # Neither of these opens a database; the scope is whatever is configured. + # Configuration-only; no database scope is resolved. app = HaikuRAGApp(config=config, read_only=True) app.show_settings() diff --git a/haiku_rag_slim/haiku/rag/client/__init__.py b/haiku_rag_slim/haiku/rag/client/__init__.py index c13a6e60..68d305e0 100644 --- a/haiku_rag_slim/haiku/rag/client/__init__.py +++ b/haiku_rag_slim/haiku/rag/client/__init__.py @@ -474,8 +474,9 @@ class HaikuRAG: await facade._release_own() self._clients.clear() await self._session.aclose() - # The set shares this client's embedder and reranker, so this is the - # only place they are closed — and only if anything built them. + # This client's own: the reranker its facades borrow, and the + # embedder it builds from configuration for work that names no + # database. Each covered database builds and closes its own. await self._aclose_cached("embedder") await self._aclose_cached("_own_reranker") self._closed = True diff --git a/haiku_rag_slim/haiku/rag/client/session.py b/haiku_rag_slim/haiku/rag/client/session.py index f52af32f..3ba3c57c 100644 --- a/haiku_rag_slim/haiku/rag/client/session.py +++ b/haiku_rag_slim/haiku/rag/client/session.py @@ -193,12 +193,14 @@ class SingleDatabaseSession: filter: str | None = None, include_content: bool = False, ) -> "list[Document]": - documents = await self.document_repository.list_all( - limit=limit, offset=offset, filter=filter, include_content=include_content + return self.name_all( + await self.document_repository.list_all( + limit=limit, + offset=offset, + filter=filter, + include_content=include_content, + ) ) - for document in documents: - document.source = self.source - return documents async def delete_document(self, document_id: str) -> bool: """Delete a document, cascading to children linked via diff --git a/haiku_rag_slim/haiku/rag/ingester/api/routes/database.py b/haiku_rag_slim/haiku/rag/ingester/api/routes/database.py index fa2f355c..2f0dc6c2 100644 --- a/haiku_rag_slim/haiku/rag/ingester/api/routes/database.py +++ b/haiku_rag_slim/haiku/rag/ingester/api/routes/database.py @@ -20,8 +20,6 @@ async def database(state: APIState = Depends(get_state)) -> DatabaseInfo: status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="database not configured", ) - # The one database the ingester writes: a configured set is refused when the - # client opens, before this app is built. [ref] = state.scope.databases one, db_path = ref.connection(state.config) return await gather_database_info(one, db_path or default_db_path(one)) diff --git a/haiku_rag_slim/haiku/rag/inspector/widgets/info_modal.py b/haiku_rag_slim/haiku/rag/inspector/widgets/info_modal.py index a5c09993..797286af 100644 --- a/haiku_rag_slim/haiku/rag/inspector/widgets/info_modal.py +++ b/haiku_rag_slim/haiku/rag/inspector/widgets/info_modal.py @@ -1,5 +1,4 @@ import asyncio -from pathlib import Path from typing import TYPE_CHECKING from textual.app import ComposeResult @@ -14,15 +13,6 @@ if TYPE_CHECKING: from haiku.rag.client import HaikuRAG -def reported_location(client: "HaikuRAG") -> "Path | str | None": - """Where the database to report on is, or None where a set is covered. - - What the client ended up covering is what says which of the two it is: a - client given one named database opens it rather than covering a set. - """ - return client.location - - async def database_lines(client: "HaikuRAG") -> list[str]: """What one database reports about itself, without naming its location. @@ -172,12 +162,10 @@ class InfoModal(ModalScreen): """Load and display database info.""" lines: list[str] = [] - location = reported_location(self.client) + location = self.client.location if location is None: - # Covering a set: report each database under its configured name, and - # each on its own, so one that cannot be opened costs its own block - # rather than the whole panel. Names only, no paths — a location - # belongs in the configuration. + # Report each database independently so one failure does not hide + # the rest. Names only: a location belongs in the configuration. blocks = await asyncio.gather( *(self._report(name) for name in sorted(self.client.source_names)) ) diff --git a/tests/test_inspector.py b/tests/test_inspector.py index 88169eee..144f6a65 100644 --- a/tests/test_inspector.py +++ b/tests/test_inspector.py @@ -352,14 +352,6 @@ class TestReportedLocation: source="alpha", ) - def test_a_covered_set_reports_no_location(self): - from haiku.rag.inspector.widgets.info_modal import reported_location - - client = MagicMock() - client.location = None - - assert reported_location(client) is None - def test_a_named_remote_database_reports_its_uri(self): session = self._session("s3://bucket/alpha.lancedb")