chore: initial import for test contour
This commit is contained in:
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service\ScheduleCache;
|
||||
|
||||
use App\Entity\Schedule;
|
||||
use App\Repository\ScheduleRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class ScheduleCacheService
|
||||
{
|
||||
private const CACHE_TTL_MINUTES = 5;
|
||||
|
||||
public function __construct(
|
||||
private ScheduleRepository $scheduleRepository,
|
||||
private EntityManagerInterface $entityManager,
|
||||
private LoggerInterface $logger
|
||||
) {
|
||||
$this->logger = $logger->withName('infoclinica-cache');
|
||||
}
|
||||
|
||||
public function getCachedSchedule(string $queryString, bool $isOnlineMode): ?array
|
||||
{
|
||||
try {
|
||||
$cacheTime = new \DateTime(sprintf('-%d minutes', self::CACHE_TTL_MINUTES));
|
||||
|
||||
$recentSchedules = $this->scheduleRepository->findByQueryModeAndTime(
|
||||
$queryString,
|
||||
$isOnlineMode,
|
||||
$cacheTime
|
||||
);
|
||||
|
||||
if (empty($recentSchedules)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->reconstructFromDatabase($recentSchedules, $isOnlineMode);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error('Error reading from cache', [
|
||||
'error' => $e->getMessage(),
|
||||
'query' => $queryString,
|
||||
'onlineMode' => $isOnlineMode
|
||||
]);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public function saveSchedule(array $scheduleData, string $queryString, bool $isOnlineMode): int
|
||||
{
|
||||
try {
|
||||
// Удаляем старые записи для этого запроса и типа расписания
|
||||
$this->scheduleRepository->removeByQueryStringAndMode($queryString, $isOnlineMode);
|
||||
|
||||
$savedCount = 0;
|
||||
$now = new \DateTime();
|
||||
|
||||
foreach ($scheduleData['schedule'] ?? [] as $department => $dates) {
|
||||
foreach ($dates as $dateString => $daySchedule) {
|
||||
$savedCount += $this->saveDaySchedule(
|
||||
$department,
|
||||
$dateString,
|
||||
$daySchedule,
|
||||
$queryString,
|
||||
$isOnlineMode,
|
||||
$now
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->logger->info('Successfully saved schedule to cache', [
|
||||
'query' => $queryString,
|
||||
'onlineMode' => $isOnlineMode,
|
||||
'saved_records' => $savedCount
|
||||
]);
|
||||
|
||||
return $savedCount;
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error('Error saving to cache', [
|
||||
'error' => $e->getMessage(),
|
||||
'query' => $queryString,
|
||||
'onlineMode' => $isOnlineMode
|
||||
]);
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
private function saveDaySchedule(
|
||||
string $department,
|
||||
string $dateString,
|
||||
array $daySchedule,
|
||||
string $queryString,
|
||||
bool $isOnlineMode,
|
||||
\DateTime $createdAt
|
||||
): int {
|
||||
$count = 0;
|
||||
|
||||
foreach ($daySchedule['intervals'] ?? [] as $interval) {
|
||||
$schedule = new Schedule();
|
||||
|
||||
$workDate = \DateTime::createFromFormat('Ymd', $dateString);
|
||||
if ($workDate === false) {
|
||||
$workDate = new \DateTime();
|
||||
}
|
||||
|
||||
// Базовые поля
|
||||
$schedule
|
||||
->setDcode((string)($daySchedule['dcode'] ?? ''))
|
||||
->setDepartment((string)$department)
|
||||
->setFilial((int)($daySchedule['filial'] ?? 0))
|
||||
->setSchedident((string)($daySchedule['schedident'] ?? ''))
|
||||
->setWorkdate($workDate)
|
||||
->setRnum((string)($daySchedule['rnum'] ?? ''))
|
||||
->setTime((string)($interval['time'] ?? ''))
|
||||
->setIsFree((bool)($daySchedule['isFree'] ?? false))
|
||||
->setOnlineMode($isOnlineMode)
|
||||
->setIntervalIsFree((bool)($interval['isFree'] ?? false))
|
||||
->setQueryString($queryString)
|
||||
->setCreatedAt($createdAt);
|
||||
|
||||
// Поля только для офлайн расписания
|
||||
if (!$isOnlineMode) {
|
||||
$schedule
|
||||
->setRfloor($daySchedule['rfloor'] ?? null)
|
||||
->setRbuilding($daySchedule['rbuilding'] ?? null);
|
||||
}
|
||||
|
||||
// Поле priceInfo только для онлайн расписания
|
||||
if ($isOnlineMode && isset($daySchedule['priceInfo'])) {
|
||||
$schedule->setPriceInfo($daySchedule['priceInfo']);
|
||||
}
|
||||
|
||||
$this->entityManager->persist($schedule);
|
||||
$count++;
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
private function reconstructFromDatabase(array $schedules, bool $isOnlineMode): array
|
||||
{
|
||||
$result = [
|
||||
'schedule' => [],
|
||||
'nearestDate' => []
|
||||
];
|
||||
|
||||
foreach ($schedules as $schedule) {
|
||||
$department = $schedule->getDepartment();
|
||||
$workDate = $schedule->getWorkdate()->format('Ymd');
|
||||
|
||||
if (!isset($result['schedule'][$department][$workDate])) {
|
||||
$dayData = [
|
||||
'schedident' => $schedule->getSchedident(),
|
||||
'rnum' => $schedule->getRnum(),
|
||||
'dcode' => $schedule->getDcode(),
|
||||
'filial' => $schedule->getFilial(),
|
||||
'intervals' => [],
|
||||
'depnum' => $department,
|
||||
'isFree' => $schedule->isFree()
|
||||
];
|
||||
|
||||
// Добавляем поля в зависимости от типа расписания
|
||||
if (!$isOnlineMode) {
|
||||
$dayData['rfloor'] = $schedule->getRfloor();
|
||||
$dayData['rbuilding'] = $schedule->getRbuilding();
|
||||
}
|
||||
|
||||
if ($isOnlineMode && $schedule->getPriceInfo()) {
|
||||
$dayData['priceInfo'] = $schedule->getPriceInfo();
|
||||
}
|
||||
|
||||
$result['schedule'][$department][$workDate] = $dayData;
|
||||
|
||||
// Сохраняем nearestDate
|
||||
if (!isset($result['nearestDate'][$department])) {
|
||||
$result['nearestDate'][$department] = (int)$workDate;
|
||||
}
|
||||
}
|
||||
|
||||
$result['schedule'][$department][$workDate]['intervals'][] = [
|
||||
'time' => $schedule->getTime(),
|
||||
'isFree' => $schedule->isIntervalIsFree()
|
||||
];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function clearOldCache(\DateTimeInterface $olderThan): int
|
||||
{
|
||||
try {
|
||||
return $this->scheduleRepository->removeOlderThan($olderThan);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error('Error clearing old cache', [
|
||||
'error' => $e->getMessage()
|
||||
]);
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
public function getCacheStats(): array
|
||||
{
|
||||
return $this->scheduleRepository->getCacheStatistics();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user