pythonBin = $pythonBin; $this->scriptPath = $scriptPath; $this->indexNdjsonPath = $indexNdjsonPath; $this->vectorIndexPath = $vectorIndexPath; $this->vectorMetaPath = $vectorIndexPath . '.meta.json'; $this->timeoutSeconds = $timeoutSeconds; $this->configurationProvider = $configurationProvider; } public function rebuildFromNdjson(?string $logPath = null): void { $this->assertPreconditions(); if (!is_file($this->indexNdjsonPath) || filesize($this->indexNdjsonPath) === 0) { @unlink($this->vectorIndexPath); @unlink($this->vectorMetaPath); return; } $config = $this->configurationProvider->getConfiguration(); $embeddingModel = $config->getEmbeddingModel(); $tmpVectorIndexPath = $this->vectorIndexPath . '.tmp'; $tmpVectorMetaPath = $tmpVectorIndexPath . '.meta.json'; @unlink($tmpVectorIndexPath); @unlink($tmpVectorMetaPath); $cmd = [ $this->pythonBin, $this->scriptPath, '--index', $this->indexNdjsonPath, '--out', $tmpVectorIndexPath, '--model', $embeddingModel, ]; $process = new Process($cmd); $process->setTimeout($this->timeoutSeconds); $this->runProcess($process, $logPath); $this->validateOutputs($tmpVectorIndexPath, $tmpVectorMetaPath); $this->atomicSwitchPair( $tmpVectorIndexPath, $tmpVectorMetaPath ); } private function assertPreconditions(): void { if (!is_file($this->scriptPath)) { throw new \RuntimeException('Vector build script not found.'); } if (!is_file($this->indexNdjsonPath)) { throw new \RuntimeException('index.ndjson not found.'); } } private function validateOutputs(string $tmpIndex, string $tmpMeta): void { if (!is_file($tmpIndex) || filesize($tmpIndex) === 0) { throw new \RuntimeException('Vector index tmp missing or empty'); } if (!is_file($tmpMeta) || filesize($tmpMeta) === 0) { throw new \RuntimeException('Vector meta tmp missing or empty'); } } private function atomicSwitchPair(string $tmpIndex, string $tmpMeta): void { if (!rename($tmpIndex, $this->vectorIndexPath)) { throw new \RuntimeException('Atomic switch failed for vector index'); } if (!rename($tmpMeta, $this->vectorMetaPath)) { throw new \RuntimeException('Atomic switch failed for vector meta'); } } private function runProcess(Process $process, ?string $logPath): void { $process->run(); if (!$process->isSuccessful()) { throw new ProcessFailedException($process); } } }