chunks = $chunks ?? new ChunkSearchIndexRepository(); $this->index = $index ?? new OpenSearchChunkIndex(); } public function handle(array $task): int { if (($task['target_type'] ?? null) !== 'archive') { return 0; } $archiveUid = trim((string) ($task['target_uid'] ?? '')); if ($archiveUid === '') { return 0; } $documents = $this->chunks->findQueuedDocuments($archiveUid, (int) config('opensearch.bulk.chunk_size', 500)); if ($documents === []) { return 0; } $chunkUids = array_column($documents, 'chunk_uid'); $this->chunks->markIndexing($chunkUids); try { $documents = $this->validatedDocuments($documents); if ($documents === []) { return 0; } $chunkUids = array_column($documents, 'chunk_uid'); $this->index->ensureExists(); $response = $this->index->bulkIndex($documents); $failedChunkUids = $this->failedChunkUids($response); if ($failedChunkUids !== []) { $this->chunks->markFailed($failedChunkUids, 'OpenSearch bulk index returned item errors.', true); } $indexedChunkUids = array_values(array_diff($chunkUids, $failedChunkUids)); $this->chunks->markIndexed($indexedChunkUids); return count($chunkUids); } catch (Throwable $exception) { $this->chunks->markFailed($chunkUids, $exception->getMessage(), true); throw $exception; } } private function validatedDocuments(array $documents): array { $dimensions = (int) config('opensearch.vector.dimensions', 2048); $valid = []; foreach ($documents as $document) { if (($document['embedding_dimensions'] ?? 0) !== $dimensions) { $this->chunks->markFailed([$document['chunk_uid']], sprintf( 'Chunk %s embedding dimension mismatch: expected %d, got %d.', $document['chunk_uid'] ?? '', $dimensions, $document['embedding_dimensions'] ?? 0 ), false); continue; } $valid[] = $document; } return $valid; } private function failedChunkUids(array $response): array { if (($response['errors'] ?? false) !== true) { return []; } $failed = []; foreach ($response['items'] ?? [] as $item) { $result = $item['index'] ?? []; if (isset($result['error'])) { $failed[] = (string) ($result['_id'] ?? ''); } } return array_values(array_filter($failed)); } }