SuperSeller3000/src/Infrastructure/Messenger/Handler/ValidationHandler.php

95 lines
3 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
namespace App\Infrastructure\Messenger\Handler;
use App\Domain\Article\Repository\ArticleTypeRepositoryInterface;
use App\Domain\Pipeline\Repository\AIPipelineJobRepositoryInterface;
use App\Infrastructure\Messenger\Message\DraftArticleMessage;
use App\Infrastructure\Messenger\Message\JsonCodingMessage;
use App\Infrastructure\Messenger\Message\ValidationMessage;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Uid\Uuid;
#[AsMessageHandler]
final class ValidationHandler
{
private const MAX_ATTEMPTS = 3;
public function __construct(
private readonly AIPipelineJobRepositoryInterface $jobRepository,
private readonly MessageBusInterface $bus,
private readonly ?ArticleTypeRepositoryInterface $articleTypeRepository = null,
) {
}
public function __invoke(ValidationMessage $message): void
{
$job = $this->jobRepository->findById(Uuid::fromString($message->jobId));
if (null === $job) {
return;
}
$missing = $this->findMissingFields($message);
if ([] === $missing) {
$this->bus->dispatch(new DraftArticleMessage(
jobId: $message->jobId,
articleTypeId: $message->articleTypeId,
attributes: $message->attributes,
condition: 'good',
inventoryNumber: null,
serialNumber: null,
));
return;
}
if ($job->getAttemptCount() >= self::MAX_ATTEMPTS) {
$job->markNeedsReview('Validation failed after '.self::MAX_ATTEMPTS.' attempts. Missing: '.implode(', ', $missing));
$this->jobRepository->save($job);
return;
}
$job->incrementAttempt($missing);
$this->jobRepository->save($job);
$this->bus->dispatch(new JsonCodingMessage(
jobId: $message->jobId,
articleTypeId: $message->articleTypeId,
specsText: $message->specsText,
missingFields: $missing,
));
}
/** @return list<string> attribute names that are required but not present */
private function findMissingFields(ValidationMessage $message): array
{
// Empty attributes always means retry
if ([] === $message->attributes) {
return ['(no attributes returned by LLM)'];
}
if (null === $this->articleTypeRepository) {
return [];
}
$articleType = $this->articleTypeRepository->findById(Uuid::fromString($message->articleTypeId));
if (null === $articleType) {
return [];
}
$missing = [];
foreach ($articleType->getRequiredAttributeDefinitions() as $def) {
if (!\array_key_exists($def->getId()->toRfc4122(), $message->attributes)) {
$missing[] = $def->getName();
}
}
return $missing;
}
}