sequenceDiagram
autonumber
participant Core as Метод 3 (CoreSimulationEngine)
participant Reg as TickRegistryImpl
participant Map as Оперативная память (RAM кэш)
participant API as API Приложения (Black-Box бэкенд)
participant DB as База Данных Симулятора
%% ВХОД МЕТОДА И ПРОВЕРКА КЭША
Core->>Reg: Вызов fetchTwinMetrics(twin_id, tick)
activate Reg
Note over Reg: Вход метода: twin_id и номер текущего такта
Reg->>Map: Проверка: cache.get(twin_id)
Map-->>Reg: Результат: null (В памяти пусто)
%% ПАРАЛЛЕЛЬНЫЙ СБОР ДАННЫХ
Note over Reg: Запуск 4-х параллельных потоков ввода-вывода (CompletableFuture)
par Запрос 1: Внешнее API приложения по сети
Reg->>API: HTTP GET /api/v1/fridge/products (Заголовок X-Twin-ID)
API-->>Reg: Ответ: JSON (Список продуктов в холодильнике)
and Запрос 2: Внутренняя БД симулятора (Личные веса)
Reg->>DB: SQL SELECT FROM twin_weight_preferences WHERE twin_id = ?
DB-->>Reg: Ответ: Набор строк (категория, личный вес K)
and Запрос 3: Внутренняя БД симулятора (Характер и Лень)
Reg->>DB: SQL SELECT FROM twin_profiles WHERE twin_id = ?
DB-->>Reg: Ответ: Строка профиля (laziness_coefficient)
and Запрос 4: Внутренняя БД симулятора (История еды)
Reg->>DB: SQL SELECT FROM twin_state_snapshots WHERE twin_id = ?
DB-->>Reg: Ответ: Строка снапшота (last_tick_updated)
end
%% ОБЪЕДИНЕНИЕ И ПЕРЕДАЧА УПРАВЛЕНИЯ
Note over Reg: Сборка результатов в единый пакет RawExtractionPacket
Note over Reg: Выход метода: Передача сырого пакета на шаг аналитической свертки
Reg-->>Core: Вызов метода 5 compileAndCommitMetrics(twin_id, tick, packet)
deactivate Reg
fetch_twin_metrics()
Домен: SIMULATION | Контур: Сбор данных пользователя при холодном старте
В открытом доступе представлена демонстрационная версия метода. В настоящей публичной документации отображены не все шаги, технические сценарии и приватные эндпоинты для системы цифровых симуляторов бизнес-процессов.
- Полная спецификация метода: Будет доступна только во внутреннем контуре разработки (Confluence / Swagger Enterprise).
1. Бизнес-спецификация метода
- Идентификатор метода:
BPDS-SIM-M04 - Системное имя:
fetch_twin_metrics() - Микросервис:
simulation-core-engine - Домен:
SIMULATION - Класс / Компонент:
simulation.engine.registry.TickRegistryImpl
1.1. Описание логики работы
Этот метод отвечает за наполнение оперативной памяти симулятора данными о пользователе, если их там не оказалось (ситуация Cache Miss). Метод работает как параллельный «пылесос» данных. Чтобы виртуальный поток пользователя не простаивал, симулятор одновременно запускает четыре независимых запроса: один улетает по сети в реальное приложение (бэкенд) за списком продуктов в холодильнике, а остальные три идут во внутреннюю базу данных симулятора за личными привычками, весами и историей голода.
1.2. Пошаговое выполнение
- Проверка памяти: Метод заглядывает в оперативную память (
ConcurrentHashMap). Если данные пользователя там уже есть, он мгновенно возвращает их, завершая работу. - Параллельный старт (Если в RAM пусто): Симулятор запускает асинхронный каскад из четырех одновременных запросов:
- Запрос 1 (Сетевой): HTTP-запрос к API приложения для получения списка продуктов в холодильнике бэкенда.
- Запрос 2 (База данных): SQL-выборка текущих личных весов пользователя из таблицы
twin_weight_preferences. - Запрос 3 (База данных): SQL-выборка черт характера (коэффициент лени) из таблицы
twin_profiles. - Запрос 4 (База данных): SQL-выборка времени последнего приема пищи из таблицы
twin_state_snapshots.
- Ожидание и Агрегация: Поток симуляции дожидается ответов от всех четырех источников, объединяет их в один сырой пакет данных (
RawExtractionPacket) и передает его следующему методу (Метод 5) для расчета голода.
2. Диаграмма последовательности метода (Вход и Выход флоу)
Диаграмма наглядно показывает, как метод при отсутствии данных в оперативной памяти параллельно штурмует сетевой API-шлюз приложения и три независимые таблицы PostgreSQL симулятора.
3. Схемы данных и SQL-взаимодействие
Этот метод выполняет три точечных SQL-запроса на чтение к внутренней базе данных симулятора.
3.1. Запрос к таблице личных весов пользователя (Запрос 2)
SELECT category_id, preference_weight_k
FROM simulation.twin_weight_preferences
WHERE twin_id = ?::uuid;3.2. Запрос к таблице характера и лени (Запрос 3)
SELECT chronotype, laziness_coefficient
FROM simulation.twin_profiles
WHERE twin_id = ?::uuid;3.3. Запрос к таблице истории еды (Запрос 4)
SELECT hunger_x0, last_tick_updated
FROM simulation.twin_state_snapshots
WHERE twin_id = ?::uuid;4. Спецификация обмена данными (Вход / Выход и Сетевые контракты)
Метод выполняет один внешний сетевой HTTP-запрос к приложению (бэкенду) в режиме «черного ящика».
4.1. Сетевой HTTP-запрос к приложению (Запрос 1)
GET /api/v1/fridge/products HTTP/1.1
Host: almaty-backend-gateway:8080
X-Shop-Token: almaty_retail_secret_hash_2026
X-Twin-ID: d3b07384-d113-4956-bf8a-e421cd7bf777
X-Request-ID: req-t105-active-d3b07384
Accept: application/json
4.2. Сетевой HTTP-ответ от приложения (Данные для сборки пакета)
Бэкенд возвращает актуальный список продуктов, которые прямо сейчас физически лежат в его базе данных:
[
{
"fridge_item_id": "3cb294dd-e011-4f11-b552-111122223333",
"sku": "BANANA_ECUADOR_KG",
"category_id": "FRUITS",
"quantity": 1.6950,
"unit": "kg",
"added_at": "2026-08-08T18:30:00Z"
}
]5. ЗАДАЧА ДЛЯ РАЗРАБОТЧИКА: BACKEND
Заголовок: Реализация неблокирующего контура параллельного сбора данных fetch_twin_metrics
5.1. Что нужно сделать
- Написать Java-класс
TickRegistryImplв пакетеsimulation.engine.registry, реализующий интерфейсTickRegistry. Пометить аннотацией@Component. - Внедрить в класс карту оперативной памяти
ConcurrentHashMap<UUID, TwinContext>. - Настроить параллельное выполнение четырех запросов с использованием
CompletableFuture.supplyAsync(). - В качестве исполнителя асинхронных задач передать пул виртуальных потоков Java (
Executors.newVirtualThreadPerTaskExecutor()), чтобы сетевые ожидания (I/O Wait) не блокировали физические ядра процессора. - Для отправки HTTP-запроса к приложению использовать встроенный Spring
RestClientилиWebClient, передавая обязательные заголовкиX-Twin-IDиX-Request-ID. - Собрать результаты всех четырех асинхронных задач через метод
CompletableFuture.allOf().thenApply()в один общий объект-рекордRawExtractionPacketи передать его во внутренний метод обработки (Метод 5).
6. ЗАДАЧА ДЛЯ РАЗРАБОТЧИКА: МИГРАЦИЯ
Заголовок: Индексация таблиц snapshots и preferences для ускорения параллельного чтения
6.1. Что нужно сделать
Когда 1500 виртуальных потоков пользователей одновременно запустят этот метод при старте, база данных симулятора получит резкий шквал параллельных SQL-запросов по ключу twin_id. Чтобы база данных не зависла, необходимо наложить B-Tree индексы на таблицы истории и личных весов симулятора.
-- Индекс для быстрого поиска истории приема пищи твина
CREATE UNIQUE INDEX IF NOT EXISTS idx_twin_snapshots_twin_id_lookup
ON simulation.twin_state_snapshots (twin_id);
-- Индекс для быстрой выгрузки карты личных весов твина
CREATE INDEX IF NOT EXISTS idx_twin_weights_twin_id_batch_lookup
ON simulation.twin_weight_preferences (twin_id);