fix: serialize vector indexing and deletion
This commit is contained in:
@@ -24,11 +24,13 @@ class IndexWorker:
|
||||
session_factory: async_sessionmaker,
|
||||
embeddings: EmbeddingProvider,
|
||||
vector_store: MilvusVectorStore,
|
||||
vector_mutation_lock: asyncio.Lock,
|
||||
) -> None:
|
||||
self.settings = settings
|
||||
self.session_factory = session_factory
|
||||
self.embeddings = embeddings
|
||||
self.vector_store = vector_store
|
||||
self.vector_mutation_lock = vector_mutation_lock
|
||||
self.queue: asyncio.Queue[str] = asyncio.Queue()
|
||||
self._task: asyncio.Task[None] | None = None
|
||||
|
||||
@@ -77,7 +79,8 @@ class IndexWorker:
|
||||
stored_path = document.stored_path
|
||||
file_type = document.file_type
|
||||
try:
|
||||
await asyncio.to_thread(self.vector_store.delete_document, document_id)
|
||||
async with self.vector_mutation_lock:
|
||||
await asyncio.to_thread(self.vector_store.delete_document, document_id)
|
||||
async with self.session_factory() as session:
|
||||
await DocumentRepository(session).replace_chunks(document_id, [])
|
||||
pages = await asyncio.to_thread(load_document, Path(stored_path), file_type)
|
||||
@@ -102,7 +105,9 @@ class IndexWorker:
|
||||
]
|
||||
async with self.session_factory() as session:
|
||||
await DocumentRepository(session).replace_chunks(document_id, orm_chunks)
|
||||
await self._embed_and_upsert(prepared)
|
||||
completed = await self._embed_and_upsert(document_id, prepared)
|
||||
if not completed:
|
||||
return
|
||||
async with self.session_factory() as session:
|
||||
await DocumentRepository(session).mark_indexed(document_id, len(prepared))
|
||||
except asyncio.CancelledError:
|
||||
@@ -113,12 +118,17 @@ class IndexWorker:
|
||||
logger.exception("Document indexing failed document_id=%s", document_id)
|
||||
await self._mark_failed(document_id, "INDEXING_FAILED", "文档索引失败,请重试")
|
||||
|
||||
async def _embed_and_upsert(self, chunks: list[PreparedChunk]) -> None:
|
||||
async def _embed_and_upsert(self, document_id: str, chunks: list[PreparedChunk]) -> bool:
|
||||
batch_size = 20
|
||||
for start in range(0, len(chunks), batch_size):
|
||||
batch = chunks[start : start + batch_size]
|
||||
vectors = await self.embeddings.embed_documents([chunk.content for chunk in batch])
|
||||
await asyncio.to_thread(self.vector_store.upsert, batch, vectors)
|
||||
async with self.vector_mutation_lock:
|
||||
async with self.session_factory() as session:
|
||||
if not await DocumentRepository(session).is_indexing(document_id):
|
||||
return False
|
||||
await asyncio.to_thread(self.vector_store.upsert, batch, vectors)
|
||||
return True
|
||||
|
||||
async def _mark_failed(self, document_id: str, code: str, message: str) -> None:
|
||||
async with self.session_factory() as session:
|
||||
|
||||
Reference in New Issue
Block a user