feat: improved contingents api performance with db backed snapshots
This commit is contained in:
@@ -60,4 +60,20 @@ class AccommodationRepository extends ServiceEntityRepository
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* Every accommodation that is addressable by a calendar hotel code, ordered for stable output.
|
||||
*
|
||||
* @return Accommodation[]
|
||||
*/
|
||||
public function findAllWithCalendarCode(): array
|
||||
{
|
||||
return $this->createQueryBuilder('a')
|
||||
->andWhere('a.calendarCode IS NOT NULL')
|
||||
->andWhere("a.calendarCode != ''")
|
||||
->orderBy('a.calendarCode', 'ASC')
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository\Groups;
|
||||
|
||||
use App\Entity\Groups\Accommodation;
|
||||
use App\Entity\Groups\ContingentDay;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<ContingentDay>
|
||||
*/
|
||||
class ContingentDayRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, ContingentDay::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the snapshot days within [dateFrom, dateTo] for the accommodation
|
||||
* identified by the given hotel code, keyed by Y-m-d.
|
||||
*
|
||||
* @return array<string, ContingentDay>
|
||||
*/
|
||||
public function findByHotelCodeAndDateRange(
|
||||
string $hotelCode,
|
||||
\DateTimeImmutable $dateFrom,
|
||||
\DateTimeImmutable $dateTo,
|
||||
): array {
|
||||
/** @var ContingentDay[] $days */
|
||||
$days = $this->createQueryBuilder('cd')
|
||||
->join('cd.accommodation', 'a')
|
||||
->where('a.calendarCode = :hotelCode')
|
||||
->andWhere('cd.date >= :dateFrom')
|
||||
->andWhere('cd.date <= :dateTo')
|
||||
->setParameter('hotelCode', $hotelCode)
|
||||
->setParameter('dateFrom', $dateFrom)
|
||||
->setParameter('dateTo', $dateTo)
|
||||
->orderBy('cd.date', 'ASC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
|
||||
return $this->indexByDate($days);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as above but for a known accommodation; used by the sync to diff against.
|
||||
*
|
||||
* @return array<string, ContingentDay>
|
||||
*/
|
||||
public function findByAccommodationAndDateRange(
|
||||
Accommodation $accommodation,
|
||||
\DateTimeImmutable $dateFrom,
|
||||
\DateTimeImmutable $dateTo,
|
||||
): array {
|
||||
/** @var ContingentDay[] $days */
|
||||
$days = $this->createQueryBuilder('cd')
|
||||
->where('cd.accommodation = :accommodation')
|
||||
->andWhere('cd.date >= :dateFrom')
|
||||
->andWhere('cd.date <= :dateTo')
|
||||
->setParameter('accommodation', $accommodation)
|
||||
->setParameter('dateFrom', $dateFrom)
|
||||
->setParameter('dateTo', $dateTo)
|
||||
->orderBy('cd.date', 'ASC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
|
||||
return $this->indexByDate($days);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the accommodation's complete stored snapshot as an ordered "Y-m-d:STATUS" list.
|
||||
*
|
||||
* Scalar hydration keeps the fingerprint cheap: the entities themselves are of no interest here.
|
||||
*
|
||||
* @return list<string>
|
||||
*/
|
||||
public function findStatusFingerprintParts(Accommodation $accommodation): array
|
||||
{
|
||||
/** @var array<int, array{date: \DateTimeImmutable, status: \App\BpnConnect\Model\ContingentStatus}> $rows */
|
||||
$rows = $this->createQueryBuilder('cd')
|
||||
->select('cd.date', 'cd.status')
|
||||
->where('cd.accommodation = :accommodation')
|
||||
->setParameter('accommodation', $accommodation)
|
||||
->orderBy('cd.date', 'ASC')
|
||||
->getQuery()
|
||||
->getArrayResult();
|
||||
|
||||
return array_map(
|
||||
static fn (array $row) => $row['date']->format('Y-m-d').':'.$row['status']->value,
|
||||
$rows,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retention: drops snapshot days that are in the past and can no longer be requested.
|
||||
*/
|
||||
public function deleteBefore(\DateTimeImmutable $date): int
|
||||
{
|
||||
return (int) $this->createQueryBuilder('cd')
|
||||
->delete()
|
||||
->where('cd.date < :date')
|
||||
->setParameter('date', $date)
|
||||
->getQuery()
|
||||
->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ContingentDay[] $days
|
||||
*
|
||||
* @return array<string, ContingentDay>
|
||||
*/
|
||||
private function indexByDate(array $days): array
|
||||
{
|
||||
$indexed = [];
|
||||
|
||||
foreach ($days as $day) {
|
||||
$indexed[$day->getDate()->format('Y-m-d')] = $day;
|
||||
}
|
||||
|
||||
return $indexed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Repository\Groups;
|
||||
|
||||
use App\Entity\Groups\Accommodation;
|
||||
use App\Entity\Groups\ContingentSyncState;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<ContingentSyncState>
|
||||
*/
|
||||
class ContingentSyncStateRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, ContingentSyncState::class);
|
||||
}
|
||||
|
||||
public function findOneByAccommodation(Accommodation $accommodation): ?ContingentSyncState
|
||||
{
|
||||
return $this->findOneBy(['accommodation' => $accommodation]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns every sync state keyed by accommodation id, for the revisions endpoint.
|
||||
*
|
||||
* @return array<int, ContingentSyncState>
|
||||
*/
|
||||
public function findAllIndexedByAccommodationId(): array
|
||||
{
|
||||
$indexed = [];
|
||||
|
||||
foreach ($this->findAll() as $state) {
|
||||
$accommodation = $state->getAccommodation();
|
||||
|
||||
if (null === $accommodation || null === $accommodation->getId()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$indexed[$accommodation->getId()] = $state;
|
||||
}
|
||||
|
||||
return $indexed;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user