71 lines
2.3 KiB
Python
71 lines
2.3 KiB
Python
"""项目文件变更后的后台向量索引同步。"""
|
|
import asyncio
|
|
import logging
|
|
from typing import Set
|
|
|
|
from app.core.database import AsyncSessionLocal
|
|
from app.services.zvec_service import zvec_service
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class FileVectorSyncService:
|
|
"""使用独立数据库会话串行同步单个项目的文件向量。"""
|
|
|
|
def __init__(self):
|
|
self._project_locks = {}
|
|
self._tasks: Set[asyncio.Task] = set()
|
|
|
|
def revectorize(self, project_id: int, file_path: str) -> None:
|
|
self._schedule(project_id, "revectorize", file_path)
|
|
|
|
def delete(self, project_id: int, file_path: str) -> None:
|
|
self._schedule(project_id, "delete", file_path)
|
|
|
|
def move(self, project_id: int, old_path: str, new_path: str) -> None:
|
|
self._schedule(project_id, "move", old_path, new_path)
|
|
|
|
def _schedule(
|
|
self,
|
|
project_id: int,
|
|
operation: str,
|
|
file_path: str,
|
|
new_path: str = "",
|
|
) -> None:
|
|
task = asyncio.create_task(
|
|
self._run(project_id, operation, file_path, new_path)
|
|
)
|
|
self._tasks.add(task)
|
|
task.add_done_callback(self._tasks.discard)
|
|
|
|
async def _run(
|
|
self,
|
|
project_id: int,
|
|
operation: str,
|
|
file_path: str,
|
|
new_path: str,
|
|
) -> None:
|
|
lock = self._project_locks.setdefault(project_id, asyncio.Lock())
|
|
async with lock:
|
|
async with AsyncSessionLocal() as db:
|
|
try:
|
|
if operation == "delete":
|
|
await zvec_service.delete_vector(db, project_id, file_path)
|
|
elif operation == "move":
|
|
await zvec_service.delete_vector(db, project_id, file_path)
|
|
await zvec_service.revectorize_path(db, project_id, new_path)
|
|
else:
|
|
await zvec_service.revectorize_path(db, project_id, file_path)
|
|
except Exception:
|
|
await db.rollback()
|
|
logger.exception(
|
|
"File vector sync failed: project=%s operation=%s path=%s",
|
|
project_id,
|
|
operation,
|
|
file_path,
|
|
)
|
|
|
|
|
|
file_vector_sync_service = FileVectorSyncService()
|