sequenceDiagram
autonumber
actor User as Пользователь (Экран Холодильника)
participant APP as Мобильное приложение (Flutter)
participant API as Бэкенд-шлюз (FastAPI)
participant DB as Реляционная СУБД (PostgreSQL)
User->>APP: Открывает экран склада / Триггер авто-обновления после зачисления
APP->>API: HTTP GET /api/v1/fridge/stock (С токеном в заголовках)
activate API
Note over API: Шаг 3: Декодирование JWT (Выделение user_id и home_group_id)
API->>DB: SELECT item_id, product_name, quantity, unit FROM fridge_inventory WHERE home_group_id = \$1 AND quantity > 0
activate DB
Note over DB: Оптимизированное чтение по индексу idx_fridge_stock_group
DB-->>API: Массив строк из PostgreSQL (Record Set)
deactivate DB
Note over API: Шаг 6: Маппинг Record Set в Pydantic-схему (Генерация ui_key)
API-->>APP: HTTP 200 OK (JSON-пакет с массивом nodes)
deactivate API
Note over APP: Лоадер исчезает, Flutter (Bloc/Riverpod) перерисовывает живой список продуктов
Метод GET /api/v1/fridge/stock
Метод ручного текстового ввода ресурсов. Документация микросервисов домена fridge
- PURCHSASE-2XX Backlog — Краткое Описание задачи 1.
- PURCHSASE-1XX Refinement (Уточнение) — Краткое Описание задачи 2.
1 Часть 1: Системный контракт, схема инвентаря и валидация данных
Этот документ описывает внутреннюю логику, структуру чтения и спецификацию контракта для основного синхронного метода выгрузки ресурсов. Метод реализует логику атомарного чтения текущего живого инвентаря конкретной домашней группы или офиса, обеспечивая реактивную синхронизацию UI мобильного приложения Flutter сразу после завершения транзакций зачисления (ручного ввода, апрува чеков или медиа-модерации).
1.1 1. Функциональное назначение метода
Эндпоинт предназначен для получения актуального списка продуктов и их точного количества, находящихся в «цифровом холодильнике» конкретной семьи либо человека. Данные используются клиентским мобильным приложением FoodLifecycleApp (Flutter) для динамического построения интерфейсных карточек склада и плиток подбора ингредиентов (selectorNode).
Метод решает следующие критические задачи домена: 1. Реактивная синхронизация интерфейса: Выступает финальной точкой автоматического Pull-обновления (Шаг 22 в фото-контуре, Шаг 14 в ручном вводе), когда Flutter запрашивает актуальный стейт остатков сразу после успешного коммита транзакций добавления (HTTP 201). 2. Фильтрация нулевых балансов: Автоматически отсекает продукты питания, баланс которых опустился до нуля (\(quantity \le 0\)), предотвращая отображение фантомных карточек еды в интерфейсе. 3. Обогащение UI-метаданными: Возвращает JSON-ноды продуктов с привязанными уникальными ui_key и техническими словарями (metadata) для отрисовки сроков годности и категорий каталога.
1.2 2. Протокол взаимодействия (HTTP Контракт)
- Метод:
GET - Маршрут:
/api/v1/fridge/stock - Формат данных:
application/json
1.2.1 Спецификация заголовков (Request Headers)
| Заголовок | Обязательный | Описание | Пример значения |
|---|---|---|---|
Content-Type |
Да | Указывает на получение строго типизированного JSON-пакета | application/json |
Authorization |
Да | Авторизационный токен в формате Bearer <JWT_TOKEN>. Выделяет user_id и home_group_id. |
Bearer eyJhbGciOiJIUzI1Ni... |
X-Request-ID |
Да | Сквозной ID запроса для распределенного логирования | req-get-stock-11xx |
1.2.2 Спецификация тела ответа (Response Body - 200 OK)
| Поле | Тип | Обязательный | Описание | Пример значения |
|---|---|---|---|---|
home_group_id |
String | Да | Уникальный строковый идентификатор домашней группы (семьи/офиса) | "group-772-alpha" |
nodes |
Array (Object) | Да | Массив объектов (нод) доступных на складе продуктов | [...] |
2 Часть 2: Схема обработки запроса и пошаговая транзакционность чтения
2.1 1. Схема обработки запроса пользователя (Mermaid)
На диаграмме представлена внутренняя логика синхронного выгружения остатков склада. Бэкенд-шлюз FastAPI декодирует токен, извлекает параметры группы и выполняет оптимизированное по индексу чтение из реляционной СУБД PostgreSQL, возвращая строго типизированную Pydantic-структуру.
2.2 2. Расшифровка шагов пайплайна (Выгрузка остатков)
Шаг 1 (
User -> APP): Пользователь переходит на главный экран цифрового холодильника, либо мобильное приложение автоматически инициирует Pull-запрос остатков после успешного закрытия карточки модерации или ручного ввода.Шаг 2 (
APP -> API): КлиентDioотправляет запросHTTP GET /api/v1/fridge/stock. В заголовках передается обязательный Bearer Access Token сессии и сквозной идентификатор трассировкиX-Request-ID.Шаг 3 (
API -> API): Бэкенд-шлюзFastAPIпринимает запрос, декодирует JWT-токен изDepends(security), верифицирует криптографическую подпись и извлекает параметрыuser_idиhome_group_id. Метод универсален и изолирует данные контекстаHOMEот контекстаOFFICE.Шаг 4 (
API -> DB): Шлюз инициализирует асинхронное соединение с базой данныхPostgreSQLи выполняет параметризованный SQL-запрос на чтение. Для максимальной скорости выборки используется ранее созданный уникальный индексidx_fridge_stock_group:SELECT item_id, product_name, quantity, unit FROM fridge_inventory WHERE home_group_id = \$1 AND quantity > 0 ORDER BY product_name ASC;Шаг 5 (
DB -> API): База данных мгновенно возвращает отфильтрованный массив строк (Record Set), содержащий только те продукты, чей баланс строго больше нуля.Шаг 6 (
API -> API): Маппинг и Pydantic-валидация: Шлюз итерирует полученные строки, упаковывает их в JSON-ноды и динамически генерирует строковый ключui_keyна основеitem_id(например,"prod_45"), необходимый Flutter для эффективного рендеринга элементов вListView.Шаг 7 (
API -> APP): Сервер возвращает мобильному приложению статусHTTP 200 OKсо структурированным JSON-пакетом остатков.Шаг 8 (
APP -> User): Flutter-клиент гасит лоадер ожидания, стейт-менеджер обновляет локальное состояние, и на экране холодильника мгновенно отрисовывается актуальный список продуктов с точным указанием весов и штук.
3 Часть 3: Спецификация ответов сервера, вилок исключений и таймаутов
3.1 1. Спецификация успешных ответов сервера (Success Response)
3.1.1 HTTP 200 OK (Ответ на Шаге 7)
Возвращается мобильному приложению Flutter после успешного выполнения SQL-запроса чтения и маппинга данных в Pydantic-схему.
- Заголовки ответа (Response Headers):
Content-Type: application/json
- Тело ответа (Response Body):
{
"home_group_id": "group-772-alpha",
"nodes": [
{
"id": 45,
"name": "Молоко",
"qty": 2.0,
"unit": "л",
"ui_key": "prod_45",
"metadata": {
"fat_percentage": 3.2,
"expiration_date": "2026-07-15"
}
},
{
"id": 89,
"name": "АПЕЛЬСИНЫ",
"qty": 1.5,
"unit": "кг",
"ui_key": "prod_89",
"metadata": {
"variety": "Гренни Смит"
}
}
]
}3.2 2. Спецификация ошибок и вилок исключений (Error Responses)
Все ошибки бэкенда возвращаются в едином стандартизированном формате RFC 7807 (Problem Details) или стандартном JSON-формате FastAPI HTTPException. Это позволяет Flutter-клиенту (Dio) однозначно парсить код ошибки и выводить корректный текст в модальных окнах.
3.3 3. Политика READ-таймаутов и отказоустойчивости (Deadlines)
Поскольку эндпоинт получения остатков является самым часто вызываемым роутом в мобильном приложении (триггерится при каждом открытии экрана и после каждого зачисления), к нему предъявляются повышенные требования по Latency.
3.3.1 Жесткий Read Deadline
- Значение:
timeout = 0.2s(200 миллисекунд). - Обоснование: Поиск строк в таблице
fridge_inventoryпо индексированному полюhome_group_idдля одной семьи (в среднем от 20 до 100 строк) занимает на СУБД не более 2–5 мс. Ожидание ответа дольше 200 мс свидетельствует о системной деградации инфраструктуры.
3.3.2 Защита пула соединений за счет кэширования
Чтобы пиковые нагрузки чтения остатков множеством пользователей не приводили к ошибкам HTTP 503 (ERR-DATABASE-OFFLINE), рекомендуется кэшировать результат Pydantic-маппинга этого метода в распределенном In-Memory кэше Redis со сроком жизни (TTL) 60 секунд. Любой успешный INSERT/UPSERT (ручной ввод, подтверждение фото/голоса) обязан принудительно инвалидировать (стереть) кэш этой группы в Redis, заставляя следующий GET-запрос прочитать чистые данные напрямую из PostgreSQL.