diff --git a/src/Command/BpnRefreshTravelSnapshotCommand.php b/src/Command/BpnRefreshTravelSnapshotCommand.php index 5e3d7ee..e72c58c 100644 --- a/src/Command/BpnRefreshTravelSnapshotCommand.php +++ b/src/Command/BpnRefreshTravelSnapshotCommand.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace App\Command; +use App\BusProNet\XmlLoader\TravelLoader; use App\Service\TravelSnapshotService; use Psr\Log\LoggerInterface; use Symfony\Component\Console\Attribute\AsCommand; @@ -28,6 +29,7 @@ class BpnRefreshTravelSnapshotCommand extends Command public function __construct( private readonly TravelSnapshotService $snapshotService, private readonly LoggerInterface $logger, + private readonly TravelLoader $travelLoader, ) { parent::__construct(); } @@ -54,7 +56,16 @@ class BpnRefreshTravelSnapshotCommand extends Command $force = true === $input->getOption('force'); $refreshAfterMinutes = (int) $input->getOption('refresh-after'); - $result = $this->snapshotService->refreshExtendedSnapshots($limit, $force, $refreshAfterMinutes); + $xmlDateIds = []; + try { + $xmlDateIds = array_keys($this->travelLoader->generateFilesMap()); + } catch (\Throwable $e) { + $this->logger->warning('Failed to load XML files map for snapshot refresh filtering; refreshing all snapshots', [ + 'error' => $e->getMessage(), + ]); + } + + $result = $this->snapshotService->refreshExtendedSnapshots($limit, $force, $refreshAfterMinutes, $xmlDateIds); $io->success(sprintf( 'Snapshot refresh complete: %d processed, %d updated, %d failed', diff --git a/src/Service/TravelSnapshotService.php b/src/Service/TravelSnapshotService.php index 9408536..f8e3b05 100644 --- a/src/Service/TravelSnapshotService.php +++ b/src/Service/TravelSnapshotService.php @@ -175,7 +175,7 @@ class TravelSnapshotService * * @return array{processed:int,updated:int,failed:int} */ - public function refreshExtendedSnapshots(int $limit = 500, bool $force = false, int $refreshAfterMinutes = 360): array + public function refreshExtendedSnapshots(int $limit = 500, bool $force = false, int $refreshAfterMinutes = 360, array $xmlAvailableDateIds = []): array { $dateToThreshold = new \DateTimeImmutable(sprintf('-%d days', $this->retentionBufferDays)); $refreshBefore = new \DateTimeImmutable(sprintf('-%d minutes', $refreshAfterMinutes)); @@ -184,12 +184,18 @@ class TravelSnapshotService ? $this->snapshotRepository->findAllForMapping($limit) : $this->snapshotRepository->findRefreshCandidates($dateToThreshold, $refreshBefore, $limit); + $processed = 0; $updated = 0; $failed = 0; /** @var array $extendedResponseByDateId */ $extendedResponseByDateId = []; foreach ($candidates as $snapshot) { + if ([] !== $xmlAvailableDateIds && in_array($snapshot->getDateId(), $xmlAvailableDateIds, true)) { + continue; + } + + ++$processed; $dateId = $snapshot->getDateId(); $travel = $this->deserializeTravelFromSnapshot($snapshot); if (null === $travel) { @@ -237,7 +243,7 @@ class TravelSnapshotService } return [ - 'processed' => count($candidates), + 'processed' => $processed, 'updated' => $updated, 'failed' => $failed, ]; diff --git a/tests/Service/TravelSnapshotServiceTest.php b/tests/Service/TravelSnapshotServiceTest.php index 8a90a35..a3bd537 100644 --- a/tests/Service/TravelSnapshotServiceTest.php +++ b/tests/Service/TravelSnapshotServiceTest.php @@ -408,6 +408,25 @@ class TravelSnapshotServiceTest extends TestCase $this->assertSame(['processed' => 1, 'updated' => 0, 'failed' => 1], $result); } + public function testRefreshSkipsSnapshotsWithXmlAvailable(): void + { + $payload = '{"id":100}'; + $snapshot = new TravelSnapshot(100, 200, $payload, hash('sha256', $payload)); + + $this->snapshotRepository + ->expects($this->once()) + ->method('findRefreshCandidates') + ->willReturn([$snapshot]); + + $this->apiClient + ->expects($this->never()) + ->method('getAvailabilitiesExtended'); + + $result = $this->service->refreshExtendedSnapshots(500, false, 360, [100]); + + $this->assertSame(['processed' => 0, 'updated' => 0, 'failed' => 0], $result); + } + public function testGenerateMappingBuildsCorrectStructure(): void { $hotel = new Hotel();