feat: ajout de la gestion des chapitres dans le store Manga avec des actions pour charger et mettre à jour la disponibilité des chapitres, intégration d'un écouteur Mercure pour les mises à jour en temps réel, et amélioration des composants d'interface utilisateur pour gérer les états de chargement et d'erreur.

This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2025-04-04 16:06:32 +02:00
parent e51712a800
commit 5928cfd5f0
11 changed files with 539 additions and 39 deletions

View File

@@ -69,6 +69,10 @@ readonly class ScrapeChapterHandler
$chapter->chapterNumber,
$source->getId()->getValue()
);
// Ajout de l'ID du chapitre dans le contexte du job
$job->context['chapterId'] = $command->chapterId;
$job->start();
$this->jobRepository->save($job);

View File

@@ -0,0 +1,114 @@
<?php
namespace App\Domain\Scraping\Infrastructure\EventSubscriber;
use App\Domain\Scraping\Domain\Event\ChapterScraped;
use App\Domain\Scraping\Domain\Event\ChapterScrapingFailed;
use App\Domain\Scraping\Domain\Contract\Repository\ChapterRepositoryInterface;
use App\Domain\Shared\Domain\Contract\JobRepositoryInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Mercure\HubInterface;
use Symfony\Component\Mercure\Update;
use Symfony\Component\Messenger\Attribute\AsMessageHandler;
class ScrapingEventSubscriber implements EventSubscriberInterface
{
public function __construct(
private readonly HubInterface $hub,
private readonly ChapterRepositoryInterface $chapterRepository,
private readonly JobRepositoryInterface $jobRepository,
private readonly LoggerInterface $logger
) {
}
public static function getSubscribedEvents(): array
{
return [
// Les événements sont capturés via le système de message handlers
];
}
#[AsMessageHandler]
public function onChapterScraped(ChapterScraped $event): void
{
$jobId = $event->getJobId();
$this->logger->info('ChapterScraped reçu pour le job: ' . $jobId);
$job = $this->jobRepository->get($jobId);
if (!$job) {
$this->logger->warning('Job non trouvé pour l\'ID: ' . $jobId);
return;
}
// Récupérer le chapitre associé au job
$chapterId = $job->context['chapterId'] ?? null;
$this->logger->info('ChapterId extrait du job: ' . $chapterId);
$chapter = $this->chapterRepository->getById($chapterId);
if (!$chapter) {
$this->logger->warning('Chapitre non trouvé pour l\'ID: ' . $chapterId);
return;
}
$this->logger->info('Chapitre trouvé - ID: ' . $chapter->id . ', MangaId: ' . $chapter->mangaId . ', Number: ' . $chapter->chapterNumber);
// Préparer les données à envoyer au front
$data = [
'type' => 'chapter.scraped',
'chapterId' => $chapter->id,
'mangaId' => $chapter->mangaId,
'chapterNumber' => $chapter->chapterNumber,
'isAvailable' => true,
'timestamp' => (new \DateTimeImmutable())->format('c')
];
$this->logger->info('Données préparées pour Mercure: ' . json_encode($data));
// Publier une mise à jour sur le hub Mercure
$topics = [
'manga/chapter/' . $chapter->id, // Topic spécifique au chapitre
'manga/' . $chapter->mangaId . '/chapters', // Topic pour tous les chapitres d'un manga
'scraping/status' // Topic général pour les événements de scraping
];
$this->logger->info('Topics Mercure: ' . implode(', ', $topics));
$update = new Update($topics, json_encode($data));
$this->hub->publish($update);
$this->logger->info('Mise à jour publiée sur Mercure');
}
#[AsMessageHandler]
public function onChapterScrapingFailed(ChapterScrapingFailed $event): void
{
$this->logger->info('ChapterScrapingFailed reçu pour mangaId: ' . $event->getMangaId() . ', chapter: ' . $event->getChapterNumber());
// Préparer les données à envoyer au front
$data = [
'type' => 'chapter.scraping.failed',
'mangaId' => $event->getMangaId(),
'chapterNumber' => $event->getChapterNumber(),
'reason' => $event->getReason(),
'timestamp' => (new \DateTimeImmutable())->format('c')
];
$this->logger->info('Données préparées pour Mercure: ' . json_encode($data));
// Publier une mise à jour sur le hub Mercure
$topics = [
'manga/' . $event->getMangaId() . '/chapters', // Topic pour tous les chapitres d'un manga
'scraping/status' // Topic général pour les événements de scraping
];
$this->logger->info('Topics Mercure: ' . implode(', ', $topics));
$update = new Update($topics, json_encode($data));
$this->hub->publish($update);
$this->logger->info('Mise à jour publiée sur Mercure');
}
}