Files

6.3 KiB
Raw Permalink Blame History

title
title
Расписание врача и кеш слотов (Backend)

Сценарий 2.2: Расписание и «кеш» слотов

Бизнес-цель

Пациенту показывают свободные интервалы записи к врачу в конкретном филиале и режиме (очный / онлайн). Чтобы не дёргать MIS на каждый запрос, backend хранит недавно полученное расписание и отдаёт его при повторных обращениях с теми же параметрами.

Важно для архитектуры: несмотря на название сервиса, данные кеша живут в PostgreSQL (таблица сущности Schedule), а не в Redis. Redis в этом сценарии не используется (см. ScheduleCacheService).

Точки входа

Тип Метод + URL Класс
HTTP GET /specialist/schedule?... SpecialistController::specialistSchedule
CLI app:schedule:clear-cache ClearScheduleCacheCommand (очистка старых строк)

Фактический вызов MIS выполняется внутри GetScheduleMessageHandler (см. schedule-messenger.md).

Параметры запроса расписания

Используется App\Dto\ScheduleDto:

  • st, en — границы времени (целые);
  • dcode — код врача;
  • filial — филиал (в query строка строится как filialId);
  • onlineMode — признак онлайн-расписания.

ScheduleDto::toQueryString() формирует строку для поиска в кеше и запроса к MIS (HTTP query).

Пошаговый алгоритм HTTP

  1. Контроллер наполняет DTO из query, валидирует.
  2. SpecialistService::getSchedule($dto) диспатчит GetScheduleMessage (см. отдельную статью).
  3. Хендлер сначала зовёт ScheduleCacheService::getCachedSchedule($queryString, $isOnlineMode).

Логика ScheduleCacheService

TTL («как долго живёт кеш»)

Константа CACHE_TTL_MINUTES = 5.

getCachedSchedule:

  • вычисляет порог createdAt >= now - 5 minutes;
  • ScheduleRepository::findByQueryModeAndTime($queryString, $isOnlineMode, $createdAfter);
  • если строк нет — null (промах кеша).

То есть инвалидация по времени: записи старше 5 минут не считаются валидными для ответа.

Запись и перезапись

saveSchedule перед вставкой новых слотов вызывает removeByQueryStringAndMode: удаляет все записи кеша с тем же queryString и onlineMode. Это жёсткое обновление среза расписания под ключ запроса.

Каждый слот — строка Schedule с полями врача, отделения, даты, интервала, queryString, onlineMode, createdAt и др.

Ошибки чтения из БД

В getCachedSchedule перехват Exception → лог Error reading from cache → возврат null (как промах кеша, дальше пойдут в MIS).

Инвалидация / уборка

Механизм Описание
По TTL при чтении старше 5 минут не отдаются
saveSchedule удаление предыдущих строк с тем же ключом перед insert
app:schedule:clear-cache --hours=N массовое удаление по createdAt < now - N hours через clearOldCache
Опция --stats статистика по таблице без удаления

ScheduleErrorHandlerService

Не часть кеша; вызывается из хендлера при ошибках HTTP-клиента или непойманных исключений: логирование и возврат массива с status_code, телом ответа MIS, длительностью и т.д. (см. schedule-messenger.md).

Mermaid

flowchart TD
    A[GET /specialist/schedule] --> B[ScheduleDto + validate]
    B --> C[SpecialistService.getSchedule]
    C --> H[GetScheduleMessageHandler]
    H --> D{Есть свежие Schedule строки?}
    D -->|да ≤5 мин| R[reconstructFromDatabase → ответ cached]
    D -->|нет| E[HTTP MIS intervals]
    E --> S[saveSchedule: delete old + insert Schedule rows]
    S --> R2[ответ api + _meta]

Внешние зависимости

Система Роль
PostgreSQL хранение «кеша» Schedule
Инфоклиника (MIS) источник расписания при промахе
Redis не используется в этом сценарии по текущему коду

Обработка ошибок и edge cases

  • БД недоступна при чтении кеша — лог, ответ пойдёт в MIS; если и MIS недоступна — ошибка из хендлера.
  • Пустой ответ MISnormalize / пустые массивы зависят от клиента (см. InfoclinicaClientService).
  • Несогласованность onlineMode в DTO: в контроллере в поле может попадать 0|1 из query — при строгой типизации возможны проблемы валидации (наблюдение для джуна при отладке).

Ссылки на классы

  • apps/backend/src/Controller/SpecialistController.php (specialistSchedule)
  • apps/backend/src/Dto/ScheduleDto.php
  • apps/backend/src/Service/ScheduleCache/ScheduleCacheService.php
  • apps/backend/src/Repository/ScheduleRepository.php
  • apps/backend/src/Command/ClearScheduleCacheCommand.php
  • apps/backend/src/Service/ErrorHandler/ScheduleErrorHandlerService.php

Связанный сценарий Messenger: schedule-messenger.md.