From 861cd1c02dfe1053212630afe78566d380d47a28 Mon Sep 17 00:00:00 2001 From: suguanYang Date: Fri, 28 Aug 2026 10:23:28 +0800 Subject: [PATCH] fix: normalize native retrieval database url --- ...t_retrieval_lazy_snapshot_quality_contract.py | 16 ++++++++++++++++ .../services/retrieval/nav/nav_knowhere.py | 6 +++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/apps/api/tests/contract/test_retrieval_lazy_snapshot_quality_contract.py b/apps/api/tests/contract/test_retrieval_lazy_snapshot_quality_contract.py index 782f01f9..13c5bcf4 100644 --- a/apps/api/tests/contract/test_retrieval_lazy_snapshot_quality_contract.py +++ b/apps/api/tests/contract/test_retrieval_lazy_snapshot_quality_contract.py @@ -11,6 +11,7 @@ NamespaceKnowhereProvider, SectionRow, UnitRow, + knowhere_database_url, ) from shared.services.retrieval.nav.nav_map_scores import ( build_score_units, @@ -174,3 +175,18 @@ def test_streaming_scorer_preserves_duplicate_id_eager_semantics() -> None: } assert score_unit_stream_hybrid_all(lambda: rows, "alpha beta") == eager_scores + + +def test_native_chunk_store_strips_async_driver_from_database_url( + monkeypatch: Any, +) -> None: + monkeypatch.setenv( + "DATABASE_URL", + "postgresql+asyncpg://prod-user:prod-password@db.example/knowhere", + ) + monkeypatch.delenv("KNOWHERE_DATABASE_URL", raising=False) + + assert ( + knowhere_database_url() + == "postgresql://prod-user:prod-password@db.example/knowhere" + ) diff --git a/packages/shared-python/shared/services/retrieval/nav/nav_knowhere.py b/packages/shared-python/shared/services/retrieval/nav/nav_knowhere.py index d73eb178..c2c13187 100644 --- a/packages/shared-python/shared/services/retrieval/nav/nav_knowhere.py +++ b/packages/shared-python/shared/services/retrieval/nav/nav_knowhere.py @@ -132,7 +132,11 @@ def knowhere_database_url() -> str: or str(os.environ.get("DATABASE_URL") or "").strip() ) if configured: - return configured.replace("postgresql+asyncpg", "postgresql+psycopg2") + # ``ReadOnlyChunkStore`` uses psycopg2's native connector, which + # accepts libpq URLs but not SQLAlchemy's ``+driver`` suffix. + return configured.replace("postgresql+asyncpg://", "postgresql://", 1).replace( + "postgresql+psycopg2://", "postgresql://", 1 + ) return _DEFAULT_DSN