feat: improved contingents api performance with db backed snapshots
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Command;
|
||||
|
||||
use App\Command\BpnSyncContingentsCommand;
|
||||
use App\Entity\Groups\Accommodation;
|
||||
use App\Model\ContingentSyncResult;
|
||||
use App\Repository\Groups\AccommodationRepository;
|
||||
use App\Repository\Groups\ContingentDayRepository;
|
||||
use App\Repository\Groups\ContingentSyncStateRepository;
|
||||
use App\Service\ContingentSnapshotManager;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Log\NullLogger;
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
/**
|
||||
* The exit code drives zenstruck's failure mail, and this task runs every 15 minutes — so what
|
||||
* counts as "failed" is a deliberate decision, not an implementation detail.
|
||||
*/
|
||||
class BpnSyncContingentsCommandTest extends TestCase
|
||||
{
|
||||
public function testTotalFailureFailsTheTask(): void
|
||||
{
|
||||
$tester = $this->runSync(['A', 'B'], [
|
||||
ContingentSyncResult::failed('upstream down'),
|
||||
ContingentSyncResult::failed('upstream down'),
|
||||
]);
|
||||
|
||||
self::assertSame(Command::FAILURE, $tester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testASingleFailingHotelDoesNotFailTheTask(): void
|
||||
{
|
||||
$tester = $this->runSync(['A', 'B', 'C'], [
|
||||
ContingentSyncResult::synced(true, 3, 0, 0),
|
||||
ContingentSyncResult::failed('unknown hotel code'),
|
||||
ContingentSyncResult::synced(false, 0, 0, 0),
|
||||
]);
|
||||
|
||||
self::assertSame(Command::SUCCESS, $tester->getStatusCode());
|
||||
self::assertStringContainsString('B', $tester->getDisplay());
|
||||
self::assertStringContainsString('unknown hotel code', $tester->getDisplay());
|
||||
}
|
||||
|
||||
public function testASuccessfulRunSucceeds(): void
|
||||
{
|
||||
$tester = $this->runSync(['A'], [ContingentSyncResult::synced(true, 3, 1, 0)]);
|
||||
|
||||
self::assertSame(Command::SUCCESS, $tester->getStatusCode());
|
||||
}
|
||||
|
||||
public function testARunWithNoAccommodationsSucceeds(): void
|
||||
{
|
||||
$tester = $this->runSync([], []);
|
||||
|
||||
self::assertSame(Command::SUCCESS, $tester->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $hotelCodes
|
||||
* @param ContingentSyncResult[] $results
|
||||
*/
|
||||
private function runSync(array $hotelCodes, array $results): CommandTester
|
||||
{
|
||||
$accommodations = array_map(
|
||||
static fn (string $code) => (new Accommodation())->setCalendarCode($code),
|
||||
$hotelCodes,
|
||||
);
|
||||
|
||||
$accommodationRepository = $this->createMock(AccommodationRepository::class);
|
||||
$accommodationRepository->method('findAllWithCalendarCode')->willReturn($accommodations);
|
||||
|
||||
$manager = $this->createMock(ContingentSnapshotManager::class);
|
||||
if ([] !== $results) {
|
||||
$manager->method('sync')->willReturnOnConsecutiveCalls(...$results);
|
||||
}
|
||||
|
||||
$command = new BpnSyncContingentsCommand(
|
||||
$accommodationRepository,
|
||||
$this->createMock(ContingentSyncStateRepository::class),
|
||||
$this->createMock(ContingentDayRepository::class),
|
||||
$manager,
|
||||
new NullLogger(),
|
||||
);
|
||||
|
||||
$application = new Application();
|
||||
$application->add($command);
|
||||
|
||||
$tester = new CommandTester($application->find('app:bpn:sync-contingents'));
|
||||
$tester->execute(['--horizon-months' => '1']);
|
||||
|
||||
// LockableTrait's lock lives for the life of the process, so without releasing it every
|
||||
// run after the first would exit early and these assertions would pass for the wrong reason.
|
||||
$release = new \ReflectionMethod($command, 'release');
|
||||
$release->invoke($command);
|
||||
|
||||
return $tester;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user