add document dele and rebuild faiss index

This commit is contained in:
team 1
2026-02-17 14:49:35 +01:00
parent 1bb753e071
commit fcd9488a18
6 changed files with 189 additions and 50 deletions

View File

@@ -70,19 +70,12 @@ class DocumentService
}
/**
* Aktiviert eine Version (setzt andere inaktiv) und aktualisiert den Index.
*
* Beim Aktivieren wird deterministisch sichergestellt, dass nur diese
* Version im Index vorhanden ist:
* - alle Chunks des Dokuments werden aus index.ndjson entfernt (streaming compaction)
* - die aktive Version wird neu ge-chunkt und appended
* - FAISS wird vollständig aus index.ndjson neu gebaut
* Aktiviert eine Version
*/
public function activateVersion(DocumentVersion $version): void
{
$document = $version->getDocument();
// Aktiv-Status in DB konsistent setzen (genau 1 aktive Version)
foreach ($document->getVersions() as $existingVersion) {
$existingVersion->setActive(false);
}
@@ -90,8 +83,6 @@ class DocumentService
$version->setActive(true);
$document->setCurrentVersion($version);
// Wichtig: Aktivierung soll einen Job auslösen. Damit der Job NICHT an "INDEXED" scheitert,
// setzen wir hier bewusst auf PENDING.
$version->setIngestStatus(DocumentVersion::INGEST_PENDING);
$this->em->flush();
@@ -106,6 +97,31 @@ class DocumentService
$this->em->flush();
}
/**
* HARD DELETE
*
* Entfernt das Dokument vollständig aus der Datenbank.
* Chunks und Vector-Index werden NICHT hier behandelt,
* sondern im Ingest-Job (TYPE_DOCUMENT_DELETE).
*/
public function delete(Document $document): void
{
// 1. FK-Zyklus auflösen
$document->setCurrentVersion(null);
$this->em->flush(); // <-- WICHTIG: zuerst FK nullen!
// 2. Versionen entfernen (falls kein cascade remove existiert)
foreach ($document->getVersions() as $version) {
$this->em->remove($version);
}
$this->em->flush(); // <-- Versionen löschen
// 3. Dokument löschen
$this->em->remove($document);
$this->em->flush();
}
/**
* Berechnet SHA256 Checksum
*/

View File

@@ -19,9 +19,6 @@ final class IngestOrchestrator
) {
}
/**
* SYNCHRONE Variante (falls noch genutzt)
*/
public function runForVersion(
DocumentVersion $version,
User $user,
@@ -79,9 +76,6 @@ final class IngestOrchestrator
}
}
/**
* ASYNCHRONE Variante (Detached CLI)
*/
public function runExistingJob(IngestJob $job, bool $dryRun = false): void
{
if (!$this->lockService->acquire()) {
@@ -90,7 +84,6 @@ final class IngestOrchestrator
try {
// Falls Job bereits final ist → nichts tun (idempotent)
if (in_array($job->getStatus(), [
IngestJob::STATUS_COMPLETED,
IngestJob::STATUS_FAILED,
@@ -102,7 +95,9 @@ final class IngestOrchestrator
$job->markRunning();
$this->em->flush();
// Global Reindex
// ---------------------------
// GLOBAL REINDEX
// ---------------------------
if ($job->getType() === IngestJob::TYPE_GLOBAL_REINDEX) {
if ($dryRun) {
@@ -115,6 +110,30 @@ final class IngestOrchestrator
return;
}
// ---------------------------
// DOCUMENT DELETE (NEU)
// ---------------------------
if ($job->getType() === IngestJob::TYPE_DOCUMENT_DELETE) {
$documentId = $job->getDocumentId();
if (!$documentId instanceof Uuid) {
throw new \RuntimeException('Job has no document id.');
}
if ($dryRun) {
usleep(200000);
} else {
$this->ingestFlow->deleteDocument($documentId);
}
$this->jobService->markCompleted($job);
return;
}
// ---------------------------
// DOCUMENT / ACTIVATE
// ---------------------------
$isActivateJob = $job->getType() === IngestJob::TYPE_DOCUMENT_VERSION_ACTIVATE;
if (!$isActivateJob && $job->getType() !== IngestJob::TYPE_DOCUMENT) {
@@ -141,16 +160,12 @@ final class IngestOrchestrator
$status = $version->getIngestStatus();
// Bei Aktivierungs-Jobs IMMER re-ingestieren (auch wenn die Version früher schon indexed war).
// Hintergrund: nach Aktivierung soll der Index deterministisch die aktive Version widerspiegeln.
if (!$isActivateJob) {
// Nur blockieren wenn wirklich schon indexed
if ($status === DocumentVersion::INGEST_INDEXED) {
throw new \RuntimeException('DocumentVersion already indexed.');
}
}
// RUNNING darf hier erlaubt sein (async!)
if (!$isActivateJob) {
if (!in_array($status, [
DocumentVersion::INGEST_PENDING,
@@ -200,9 +215,6 @@ final class IngestOrchestrator
}
}
/**
* Globaler Reindex (synchron)
*/
public function runGlobal(User $user, bool $dryRun = false): IngestJob
{
if (!$this->lockService->acquire()) {