refactor(scraping): job PENDING dès le POST HTTP, handler sans Doctrine
- ScrapingJob: mangaId/chapterNumber/sourceId optionnels (nullable) pour permettre la création en PENDING sans lookup DB dans le StateProcessor - ScrapeChapter: ajoute jobId (pré-généré par le StateProcessor) - ScrapeChapterStateProcessor: crée et persiste le job PENDING avant dispatch; injecte JobRepositoryInterface uniquement - ScrapeChapterHandler: supprime EntityManagerInterface, beginTransaction/ commit/rollback; charge le job existant via jobId, complete() sur succès seulement, fail() si toutes les sources échouent - ScrapeChapterHandlerTest: pré-crée le job, passe jobId dans la commande, supprime le mock EntityManagerInterface - ScrapeChapterTest: accès aux messages via static InMemoryMessageBus, vérifie la présence du jobId dans la commande dispatchée
This commit is contained in:
parent
ec4a8be934
commit
fa035bfbfa
@@ -5,13 +5,17 @@ namespace App\Domain\Scraping\Infrastructure\ApiPlatform\State\Processor;
|
||||
use ApiPlatform\Metadata\Operation;
|
||||
use ApiPlatform\State\ProcessorInterface;
|
||||
use App\Domain\Scraping\Application\Command\ScrapeChapter;
|
||||
use App\Domain\Scraping\Domain\Model\ScrapingJob;
|
||||
use App\Domain\Scraping\Infrastructure\ApiPlatform\Dto\ScrapeChapterRequest;
|
||||
use App\Domain\Shared\Domain\Contract\JobRepositoryInterface;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Symfony\Component\Messenger\MessageBusInterface;
|
||||
|
||||
final class ScrapeChapterStateProcessor implements ProcessorInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly MessageBusInterface $commandBus
|
||||
private readonly MessageBusInterface $commandBus,
|
||||
private readonly JobRepositoryInterface $jobRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -20,10 +24,11 @@ final class ScrapeChapterStateProcessor implements ProcessorInterface
|
||||
*/
|
||||
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): void
|
||||
{
|
||||
$this->commandBus->dispatch(
|
||||
new ScrapeChapter(
|
||||
$data->chapterId
|
||||
)
|
||||
);
|
||||
$jobId = Uuid::uuid4()->toString();
|
||||
$job = new ScrapingJob($jobId);
|
||||
$job->context['chapterId'] = $data->chapterId;
|
||||
$this->jobRepository->save($job);
|
||||
|
||||
$this->commandBus->dispatch(new ScrapeChapter($data->chapterId, $jobId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Domain\Scraping\Infrastructure\EventSubscriber;
|
||||
use App\Domain\Shared\Domain\Event\ChapterScraped;
|
||||
use App\Domain\Scraping\Domain\Event\ChapterScrapingFailed;
|
||||
use App\Domain\Scraping\Domain\Event\ChapterScrapingStarted;
|
||||
use App\Domain\Scraping\Domain\Event\PageScrapingProgressed;
|
||||
use App\Domain\Scraping\Domain\Contract\Repository\ChapterRepositoryInterface;
|
||||
use App\Domain\Shared\Domain\Contract\JobRepositoryInterface;
|
||||
use App\Domain\Shared\Domain\Contract\NotificationInterface;
|
||||
@@ -30,6 +31,22 @@ class ScrapingEventSubscriber implements EventSubscriberInterface
|
||||
return [];
|
||||
}
|
||||
|
||||
#[AsMessageHandler]
|
||||
public function onPageScrapingProgressed(PageScrapingProgressed $event): void
|
||||
{
|
||||
$progress = (int) round($event->getProgress()->getPercentage());
|
||||
|
||||
$update = new Update(
|
||||
'jobs/activity',
|
||||
json_encode([
|
||||
'type' => 'job.progress_updated',
|
||||
'jobId' => $event->getJobId(),
|
||||
'progress' => $progress,
|
||||
])
|
||||
);
|
||||
$this->hub->publish($update);
|
||||
}
|
||||
|
||||
#[AsMessageHandler]
|
||||
public function onChapterScrapingStarted(ChapterScrapingStarted $event): void
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user