From 9cc2e59bb7abf6a22037b3f10d78a4089c584fd1 Mon Sep 17 00:00:00 2001 From: YUAN Date: Mon, 7 Sep 2026 12:24:46 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20T-21=20=E8=AF=84=E5=AE=A1=E9=97=AD?= =?UTF-8?q?=E7=8E=AF(P1-1=20MILVUS=5FURI=20=E9=81=AE=E8=94=BD)=E2=80=94?= =?UTF-8?q?=E2=80=94milvus=5Fservice=20=E7=8E=AF=E5=A2=83=E9=98=B2?= =?UTF-8?q?=E5=BE=A1=E9=A1=BA=E5=BA=8F=E9=87=8D=E6=8E=92:=20settings=20?= =?UTF-8?q?=E5=85=88=E5=88=9D=E5=A7=8B=E5=8C=96(=E5=B9=B2=E5=87=80?= =?UTF-8?q?=E8=AF=BB=20.env)=E2=86=92os.environ=20=E5=BD=92=E4=BD=8D?= =?UTF-8?q?=E5=90=88=E6=B3=95=20http=20=E5=8D=A0=E4=BD=8D(=E4=BB=85?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E6=96=87=E4=BB=B6=20URI)=E2=86=92import=20py?= =?UTF-8?q?milvus;=20=E5=8E=9F=E9=A1=BA=E5=BA=8F=E4=B8=8B=20pydantic=20?= =?UTF-8?q?=E8=AF=BB=E5=88=B0=E8=A2=AB=E6=B1=A1=E6=9F=93=20env=20=E4=BC=9A?= =?UTF-8?q?=E6=8A=8A=20.env=20=E7=9A=84=20MILVUS=5FURI=20=E4=B8=80?= =?UTF-8?q?=E5=B9=B6=E9=81=AE=E8=94=BD(=E6=9C=80=E5=9D=8F=20import=20?= =?UTF-8?q?=E9=A1=BA=E5=BA=8F=E7=9C=9F=E8=BF=9E=E6=8E=A5=E4=BA=8B=E6=95=85?= =?UTF-8?q?);=20=E6=9C=80=E5=9D=8F=E9=A1=BA=E5=BA=8F=E6=96=AD=E8=A8=80+?= =?UTF-8?q?=E5=85=A8=E9=87=8F=20425=20=E7=BB=BF+=E7=AB=AF=E5=88=B0?= =?UTF-8?q?=E7=AB=AF=E6=A3=80=E7=B4=A2=E9=80=9A=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/service/milvus_service.py | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/app/service/milvus_service.py b/app/service/milvus_service.py index 5b83ed0..bc7e547 100644 --- a/app/service/milvus_service.py +++ b/app/service/milvus_service.py @@ -5,12 +5,13 @@ Collection 设计(冻结):docs/项目框架设计/表设计/03-milvus-coll 检索必带溯源字段(source_doc_id + source_version),且只返回已生效文档 (effective_date <= today,§2.3 合规约束)。 -环境坑(2026-09-07 实测):pymilvus 3.x 在 **import 阶段** load_dotenv() -并急切解析环境变量 MILVUS_URI,文件 URI(如本项目 .env 的 -./data/milvus.db)会让 ``import pymilvus`` 直接抛 Illegal uri。因此本模块 -在 import pymilvus **之前**用 setdefault 预置一个合法 URI(dotenv 不覆盖 -已存在变量);真实连接由 MilvusClient(uri=...) 显式传入 settings.milvus_uri, -不经过全局单例。若未来接 Standalone(Docker),.env 设合法 http URI 即可。 +环境坑(2026-09-07 实测,含评审 P1 修正):pymilvus 3.x 在 **import 阶段** +load_dotenv() 并急切解析环境变量 MILVUS_URI,文件 URI(如 .env 的 +./data/milvus.db)会让 ``import pymilvus`` 直接抛 Illegal uri。本模块的 +防御顺序:先初始化 settings(干净读 .env),再把 os.environ 的 MILVUS_URI +归位为合法 http 占位(仅替换文件 URI),最后 import pymilvus——任何其他 +顺序都会以 import 炸 / settings 遮蔽(真连接事故)两种方式踩坑。真实连接 +恒走 MilvusClient(uri=...) 显式传参,不经过全局单例。 测试:单测用真 Milvus Lite(tempfile 临时 uri,module 级 fixture 共享), 本机实测可用(0904 交接 + 0907 复测);不做 mock 双轨。 @@ -20,10 +21,22 @@ from __future__ import annotations import os -# ---- 必须先于 from pymilvus import:防 .env 的文件 URI 炸掉 import(见模块注释)---- -os.environ.setdefault("MILVUS_URI", "http://localhost:19530") +from app.config.settings import settings # noqa: E402 -from pymilvus import DataType, MilvusClient +# ---- 环境防御(顺序敏感,评审 P1 修正):必须在 settings 初始化之后、 +# from pymilvus import 之前。原因:pymilvus 3.x import 时 load_dotenv() + +# 急切解析 MILVUS_URI,.env 的文件 URI 会炸 import;但若先改 os.environ 再 +# 初始化 settings,pydantic 会读到被污染的环境变量、把 .env 的 MILVUS_URI +# 也遮蔽掉(import 顺序敏感的真连接事故)。故口径: +# ① settings 先初始化(此时环境干净,milvus_uri 拿到 .env 正确值); +# ② 再把 os.environ 的 MILVUS_URI 归位为合法 http 占位(仅文件 URI 被换, +# 合法 http 值保留),pymilvus 全局单例不再炸 import; +# ③ 真实连接恒走 MilvusClient(uri=settings.milvus_uri) 显式传参。 +_milvus_env_uri = os.environ.get("MILVUS_URI") +if _milvus_env_uri is None or not _milvus_env_uri.startswith(("http://", "https://")): + os.environ["MILVUS_URI"] = "http://localhost:19530" + +from pymilvus import DataType, MilvusClient # noqa: E402 from app.config.settings import settings