Feat: Implement additional caches for expensive db queries
This commit is contained in:
@@ -32,20 +32,30 @@ use EP\EpProducts\Domain\Model\Product;
|
|||||||
use EP\EpProducts\Domain\Repository\ContingentRepository;
|
use EP\EpProducts\Domain\Repository\ContingentRepository;
|
||||||
use EP\EpProducts\Utility\BookingUrlUtility;
|
use EP\EpProducts\Utility\BookingUrlUtility;
|
||||||
use League\Period\Period;
|
use League\Period\Period;
|
||||||
|
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
|
||||||
|
|
||||||
class ContingentDataService
|
class ContingentDataService
|
||||||
{
|
{
|
||||||
|
public const CACHE_TTL = 60 * 60;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ContingentRepository
|
* @var ContingentRepository
|
||||||
*/
|
*/
|
||||||
protected $contingentRepository;
|
protected $contingentRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ContingentRepository $contingentRepository
|
* @var FrontendInterface
|
||||||
*/
|
*/
|
||||||
public function __construct(ContingentRepository $contingentRepository)
|
private $cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ContingentRepository $contingentRepository
|
||||||
|
* @param FrontendInterface $cache
|
||||||
|
*/
|
||||||
|
public function __construct(ContingentRepository $contingentRepository, FrontendInterface $cache)
|
||||||
{
|
{
|
||||||
$this->contingentRepository = $contingentRepository;
|
$this->contingentRepository = $contingentRepository;
|
||||||
|
$this->cache = $cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,18 +66,21 @@ class ContingentDataService
|
|||||||
*/
|
*/
|
||||||
public function getAvailableContingents(Hotel $hotel, Product $product)
|
public function getAvailableContingents(Hotel $hotel, Product $product)
|
||||||
{
|
{
|
||||||
$data = $this->contingentRepository->getAvailableContingents($hotel, $product);
|
$key = 'contingents_'.sha1($hotel->getUid().$product->getUid());
|
||||||
|
|
||||||
$contingents = [];
|
if (false === $contingents = $this->cache->get($key)) {
|
||||||
|
$data = $this->contingentRepository->getAvailableContingents($hotel, $product);
|
||||||
|
$contingents = [];
|
||||||
|
foreach ($data as $row) {
|
||||||
|
$contingents[$row['date']] = [
|
||||||
|
'date' => $row['date'],
|
||||||
|
'minNights' => $row['minNights'],
|
||||||
|
'total' => $row['total'],
|
||||||
|
'capacity' => $row['capacity'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
foreach ($data as $row)
|
$this->cache->set($key, $contingents, [], self::CACHE_TTL);
|
||||||
{
|
|
||||||
$contingents[$row['date']] = [
|
|
||||||
'date' => $row['date'],
|
|
||||||
'minNights' => $row['minNights'],
|
|
||||||
'total' => $row['total'],
|
|
||||||
'capacity' => $row['capacity'],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $contingents;
|
return $contingents;
|
||||||
@@ -89,28 +102,32 @@ class ContingentDataService
|
|||||||
Product $product,
|
Product $product,
|
||||||
$template = 'base'
|
$template = 'base'
|
||||||
) {
|
) {
|
||||||
$data = $this->contingentRepository->getAvailableRooms($dateFrom, $dateTo, $hotel, $product);
|
$key = 'rooms_'.sha1($dateFrom.$dateTo.$hotel->getUid().$product->getUid());
|
||||||
$period = new Period($dateFrom, $dateTo);
|
|
||||||
$nights = $period->dateInterval()->format('%a');
|
|
||||||
|
|
||||||
$rooms = [];
|
if (false === $rooms = $this->cache->get($key)) {
|
||||||
|
$data = $this->contingentRepository->getAvailableRooms($dateFrom, $dateTo, $hotel, $product);
|
||||||
|
$period = new Period($dateFrom, $dateTo);
|
||||||
|
$nights = $period->dateInterval()->format('%a');
|
||||||
|
$rooms = [];
|
||||||
|
foreach ($data as $row) {
|
||||||
|
$row['bookingUrl'] = BookingUrlUtility::generateUrl([
|
||||||
|
'bookingId' => $row['busProId'],
|
||||||
|
'hotelId' => $row['hotelBusProId'],
|
||||||
|
'dateEnd' => $dateTo,
|
||||||
|
'template' => $template,
|
||||||
|
]);
|
||||||
|
|
||||||
foreach ($data as $row) {
|
$row['summer'] = $row['season'] === 's';
|
||||||
$row['bookingUrl'] = BookingUrlUtility::generateUrl([
|
|
||||||
'bookingId' => $row['busProId'],
|
|
||||||
'hotelId' => $row['hotelBusProId'],
|
|
||||||
'dateEnd' => $dateTo,
|
|
||||||
'template' => $template,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$row['summer'] = $row['season'] === 's';
|
$row['servicesIncluded'] = unserialize($row['servicesIncluded'], ['allowed_classes' => false]);
|
||||||
|
$row['servicesOptional'] = unserialize($row['servicesOptional'], ['allowed_classes' => false]);
|
||||||
|
|
||||||
$row['servicesIncluded'] = unserialize($row['servicesIncluded'], ['allowed_classes' => false]);
|
$row['priceForSelection'] = $row['price'] + ($nights - $row['minNights']) * $row['additionalNightPrice'];
|
||||||
$row['servicesOptional'] = unserialize($row['servicesOptional'], ['allowed_classes' => false]);
|
|
||||||
|
|
||||||
$row['priceForSelection'] = $row['price'] + ($nights - $row['minNights']) * $row['additionalNightPrice'];
|
$rooms[] = $row;
|
||||||
|
}
|
||||||
|
|
||||||
$rooms[] = $row;
|
$this->cache->set($key, $rooms, [], self::CACHE_TTL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $rooms;
|
return $rooms;
|
||||||
|
|||||||
@@ -33,12 +33,15 @@ use EP\EpProducts\Domain\Repository\DateRepository;
|
|||||||
use EP\EpProducts\Domain\Repository\ProductRepository;
|
use EP\EpProducts\Domain\Repository\ProductRepository;
|
||||||
use EP\EpProducts\Utility\BookingUrlUtility;
|
use EP\EpProducts\Utility\BookingUrlUtility;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
|
||||||
use TYPO3\CMS\Core\SingletonInterface;
|
use TYPO3\CMS\Core\SingletonInterface;
|
||||||
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
use TYPO3\CMS\Core\Utility\GeneralUtility;
|
||||||
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
|
use TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder;
|
||||||
|
|
||||||
class DateService implements SingletonInterface
|
class DateService implements SingletonInterface
|
||||||
{
|
{
|
||||||
|
public const CACHE_TTL = 60 * 60;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ProductRepository
|
* @var ProductRepository
|
||||||
*/
|
*/
|
||||||
@@ -59,6 +62,11 @@ class DateService implements SingletonInterface
|
|||||||
*/
|
*/
|
||||||
protected $uriBuilder;
|
protected $uriBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var FrontendInterface
|
||||||
|
*/
|
||||||
|
protected $cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var string[]
|
||||||
*/
|
*/
|
||||||
@@ -76,19 +84,22 @@ class DateService implements SingletonInterface
|
|||||||
* @param DateRepository $dateRepository
|
* @param DateRepository $dateRepository
|
||||||
* @param FilterService $filterService
|
* @param FilterService $filterService
|
||||||
* @param UriBuilder $uriBuilder
|
* @param UriBuilder $uriBuilder
|
||||||
|
* @param FrontendInterface $cache
|
||||||
*/
|
*/
|
||||||
public function __construct
|
public function __construct
|
||||||
(
|
(
|
||||||
ProductRepository $productRepository,
|
ProductRepository $productRepository,
|
||||||
DateRepository $dateRepository,
|
DateRepository $dateRepository,
|
||||||
FilterService $filterService,
|
FilterService $filterService,
|
||||||
UriBuilder $uriBuilder
|
UriBuilder $uriBuilder,
|
||||||
|
FrontendInterface $cache
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
$this->productRepository = $productRepository;
|
$this->productRepository = $productRepository;
|
||||||
$this->filterService = $filterService;
|
$this->filterService = $filterService;
|
||||||
$this->dateRepository = $dateRepository;
|
$this->dateRepository = $dateRepository;
|
||||||
$this->uriBuilder = $uriBuilder;
|
$this->uriBuilder = $uriBuilder;
|
||||||
|
$this->cache = $cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,8 +125,13 @@ class DateService implements SingletonInterface
|
|||||||
$filterSettings = $this->filterService->getNormalizedFilterSettings();
|
$filterSettings = $this->filterService->getNormalizedFilterSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$key = 'pricetable_'.sha1($product->getUid().$hotel->getUid().serialize($filterSettings).$date ? $date->getUid():0);
|
||||||
|
if (false === $priceTableData = $this->cache->get($key)) {
|
||||||
|
$priceTableData = $this->productRepository->getPricetable($product, $hotel, $filterSettings, $date);
|
||||||
|
$this->cache->set($key, $priceTableData, ['ep_products'], self::CACHE_TTL);
|
||||||
|
}
|
||||||
|
|
||||||
$nonBookableDateUids = GeneralUtility::trimExplode(',', $product->getNonBookableDates(), true);
|
$nonBookableDateUids = GeneralUtility::trimExplode(',', $product->getNonBookableDates(), true);
|
||||||
$priceTableData = $this->productRepository->getPricetable($product, $hotel, $filterSettings, $date);
|
|
||||||
|
|
||||||
return $this->preprocessPriceTable([
|
return $this->preprocessPriceTable([
|
||||||
'priceTableData' => $priceTableData,
|
'priceTableData' => $priceTableData,
|
||||||
@@ -152,11 +168,13 @@ class DateService implements SingletonInterface
|
|||||||
$filterSettings = $this->filterService->getNormalizedFilterSettings();
|
$filterSettings = $this->filterService->getNormalizedFilterSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->productRepository->getAvailableDates(
|
$key = 'datestable_'.sha1($product->getUid().$hotel->getUid().serialize($filterSettings));
|
||||||
$product,
|
if (false === $datesTableData = $this->cache->get($key)) {
|
||||||
$hotel,
|
$datesTableData = $this->productRepository->getAvailableDates($product, $hotel, $filterSettings);
|
||||||
$filterSettings
|
$this->cache->set($key, $datesTableData, ['ep_products'], self::CACHE_TTL);
|
||||||
);
|
}
|
||||||
|
|
||||||
|
return $datesTableData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -172,7 +190,11 @@ class DateService implements SingletonInterface
|
|||||||
|
|
||||||
public function getEventPriceTable(Product $product, int $maxPax = 99, string $template = 'base'): array
|
public function getEventPriceTable(Product $product, int $maxPax = 99, string $template = 'base'): array
|
||||||
{
|
{
|
||||||
$priceTableData = $this->productRepository->getEventPriceTable($product);
|
$key = 'pricetable_'.sha1($product->getUid());
|
||||||
|
if (false === $priceTableData = $this->cache->get($key)) {
|
||||||
|
$priceTableData = $this->productRepository->getEventPriceTable($product);
|
||||||
|
$this->cache->set($key, $priceTableData, ['ep_products'], self::CACHE_TTL);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->preprocessEventPriceTable([
|
return $this->preprocessEventPriceTable([
|
||||||
'priceTableData' => $priceTableData,
|
'priceTableData' => $priceTableData,
|
||||||
|
|||||||
@@ -29,10 +29,12 @@ namespace EP\EpProducts\Service;
|
|||||||
use EP\EpProducts\Domain\Model\Hotel;
|
use EP\EpProducts\Domain\Model\Hotel;
|
||||||
use EP\EpProducts\Domain\Repository\HotelRepository;
|
use EP\EpProducts\Domain\Repository\HotelRepository;
|
||||||
use EP\EpProducts\Domain\Repository\ProductRepository;
|
use EP\EpProducts\Domain\Repository\ProductRepository;
|
||||||
|
use TYPO3\CMS\Core\Cache\Frontend\FrontendInterface;
|
||||||
use TYPO3\CMS\Core\SingletonInterface;
|
use TYPO3\CMS\Core\SingletonInterface;
|
||||||
|
|
||||||
class ProductDataService implements SingletonInterface
|
class ProductDataService implements SingletonInterface
|
||||||
{
|
{
|
||||||
|
public const CACHE_TTL = 60 * 60;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ProductRepository
|
* @var ProductRepository
|
||||||
@@ -54,6 +56,11 @@ class ProductDataService implements SingletonInterface
|
|||||||
*/
|
*/
|
||||||
protected $hotelImageService;
|
protected $hotelImageService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var FrontendInterface
|
||||||
|
*/
|
||||||
|
protected $cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ProductRepository $productRepository
|
* @param ProductRepository $productRepository
|
||||||
* @param HotelRepository $hotelRepository
|
* @param HotelRepository $hotelRepository
|
||||||
@@ -64,12 +71,14 @@ class ProductDataService implements SingletonInterface
|
|||||||
ProductRepository $productRepository,
|
ProductRepository $productRepository,
|
||||||
HotelRepository $hotelRepository,
|
HotelRepository $hotelRepository,
|
||||||
HotelImageService $hotelImageService,
|
HotelImageService $hotelImageService,
|
||||||
ProductImageService $productImageService
|
ProductImageService $productImageService,
|
||||||
|
FrontendInterface $cache
|
||||||
) {
|
) {
|
||||||
$this->productRepository = $productRepository;
|
$this->productRepository = $productRepository;
|
||||||
$this->hotelRepository = $hotelRepository;
|
$this->hotelRepository = $hotelRepository;
|
||||||
$this->productImageService = $productImageService;
|
$this->productImageService = $productImageService;
|
||||||
$this->hotelImageService = $hotelImageService;
|
$this->hotelImageService = $hotelImageService;
|
||||||
|
$this->cache = $cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,8 +88,13 @@ class ProductDataService implements SingletonInterface
|
|||||||
*/
|
*/
|
||||||
public function getTeaser(array $filterSettings): ?array
|
public function getTeaser(array $filterSettings): ?array
|
||||||
{
|
{
|
||||||
$teaserData = $this->productRepository->getTeasers($filterSettings);
|
$key = 'teaser_group_'.sha1(serialize($filterSettings));
|
||||||
$teasers = $this->preprocessTeasergroup($teaserData);
|
|
||||||
|
if (false === $teasers = $this->cache->get($key)) {
|
||||||
|
$teaserData = $this->productRepository->getTeasers($filterSettings);
|
||||||
|
$teasers = $this->preprocessTeasergroup($teaserData);
|
||||||
|
$this->cache->set($key, $teasers, ['ep_products'], self::CACHE_TTL);
|
||||||
|
}
|
||||||
|
|
||||||
if (0 === count($teasers)) {
|
if (0 === count($teasers)) {
|
||||||
return null;
|
return null;
|
||||||
@@ -98,18 +112,27 @@ class ProductDataService implements SingletonInterface
|
|||||||
*/
|
*/
|
||||||
public function getTeasergroup(array $filterSettings, array $excludedConceptUids = [], int $limit = 0): array
|
public function getTeasergroup(array $filterSettings, array $excludedConceptUids = [], int $limit = 0): array
|
||||||
{
|
{
|
||||||
$teaserData = $this->productRepository->getTeasers($filterSettings, $excludedConceptUids);
|
$key = 'teaser_group_'.sha1(serialize($filterSettings).serialize($excludedConceptUids));
|
||||||
|
|
||||||
return $this->preprocessTeasergroup($teaserData, $limit);
|
if (false === $teasers = $this->cache->get($key)) {
|
||||||
|
$teaserData = $this->productRepository->getTeasers($filterSettings, $excludedConceptUids);
|
||||||
|
$teasers = $this->preprocessTeasergroup($teaserData);
|
||||||
|
$this->cache->set($key, $teasers, ['ep_products'], self::CACHE_TTL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($limit > 0) {
|
||||||
|
return \array_slice($teasers, 0, $limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $teasers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $teaserData
|
* @param array $teaserData
|
||||||
* @param int $limit
|
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function preprocessTeasergroup(array $teaserData, int $limit = 0): array
|
public function preprocessTeasergroup(array $teaserData): array
|
||||||
{
|
{
|
||||||
$data = [];
|
$data = [];
|
||||||
|
|
||||||
@@ -158,10 +181,6 @@ class ProductDataService implements SingletonInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($limit > 0) {
|
|
||||||
return \array_slice($data, 0, $limit);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,12 +22,20 @@ services:
|
|||||||
|
|
||||||
EP\EpProducts\Service\HotelImageService:
|
EP\EpProducts\Service\HotelImageService:
|
||||||
arguments:
|
arguments:
|
||||||
$fileRepository: '@TYPO3\CMS\Core\Resource\FileRepository'
|
|
||||||
$imageService: '@TYPO3\CMS\Extbase\Service\ImageService'
|
|
||||||
$cache: '@cache.ep_cache'
|
$cache: '@cache.ep_cache'
|
||||||
|
|
||||||
EP\EpProducts\Service\ProductImageService:
|
EP\EpProducts\Service\ProductImageService:
|
||||||
arguments:
|
arguments:
|
||||||
$fileRepository: '@TYPO3\CMS\Core\Resource\FileRepository'
|
$cache: '@cache.ep_cache'
|
||||||
$imageService: '@TYPO3\CMS\Extbase\Service\ImageService'
|
|
||||||
|
EP\EpProducts\Service\DateService:
|
||||||
|
arguments:
|
||||||
|
$cache: '@cache.ep_cache'
|
||||||
|
|
||||||
|
EP\EpProducts\Service\ProductDataService:
|
||||||
|
arguments:
|
||||||
|
$cache: '@cache.ep_cache'
|
||||||
|
|
||||||
|
EP\EpProducts\Service\ContingentDataService:
|
||||||
|
arguments:
|
||||||
$cache: '@cache.ep_cache'
|
$cache: '@cache.ep_cache'
|
||||||
|
|||||||
Reference in New Issue
Block a user