sequenceDiagram
autonumber
participant Core as CoreSimulationEngineImpl
participant Map as Оперативная память (RAM кэш)
participant DB as База Данных Симулятора
%% ВХОД МЕТОДА
Core->>Core: Вызов flushSessionState(twin_id, tick, scenario)
Note over Core: Вход метода: twin_id, текущий такт и тип завершенного действия
%% ОБНОВЛЕНИЕ ОПЕРАТИВНОЙ ПАМЯТИ
Core->>Core: Расчет новых личных весов K и сброса голода
Core->>Map: Атомарное обновление cache.replace(twin_id, newContext)
activate Map
Map-->>Core: Подтверждено (RAM обновлена)
deactivate Map
%% ФИЗИЧЕСКИЙ СБРОС В ПОСТГРЕС СИМУЛЯТОРА
Note over Core: Запуск транзакции фиксации опыта в СУБД симулятора
par Фиксация биологического времени еды
Core->>DB: SQL UPSERT INTO twin_state_snapshots (last_tick_updated = tick)
activate DB
DB-->>Core: База данных: Снапшот сохранен
deactivate DB
and Фиксация долговременных привычек
Core->>DB: SQL UPSERT INTO twin_weight_preferences (weight = K_new)
activate DB
DB-->>Core: База данных: Веса K сохранены
deactivate DB
end
Core->>Core: MDC.remove("X-Request-ID")
Note over Core: Выход метода: Успешное закрытие транзакции такта. Виртуальный поток уничтожен.
Метод 17: flush_session_state()
Домен: SIMULATION | Контур: Фиксация измененных привычек и биологических часов
В открытом доступе представлена демонстрационная версия метода. В настоящей публичной документации отображены не все шаги, технические сценарии и приватные эндпоинты для системы цифровых симуляторов бизнес-процессов.
- Полная спецификация метода: Будет доступна только во внутреннем контуре разработки (Confluence / Swagger Enterprise).
1. Бизнес-спецификация метода
- Идентификатор метода:
BPDS-SIM-M017 - Системное имя:
flush_session_state(twin_id: UUID, current_tick: Long, scenario: ScenarioEnum) - Микросервис:
simulation-core-engine - Домен:
SIMULATION - Класс / Компонент:
simulation.engine.core.CoreSimulationEngineImpl
1.1. Описание логики работы
Этот метод является финальной точкой всего часового цикла (такта) симуляции. Он запускается только тогда, когда Метод 16 подтвердил, что реальное приложение и его база данных успешно обновили продукты в холодильнике.
Задача метода — зафиксировать полученный пользователем опыт в его долговременную память. Симулятор имитирует психологию человека: 1. Насыщение: Если пользователь только что поел, симулятор обнуляет его внутренний показатель голода в оперативной памяти (RAM) и записывает номер текущего часа симуляции как время последнего приема пищи. Одновременно в базе увеличивается его интерес к готовой еде (подкрепление лени). 2. Изменение привычек: Если пользователь совершил закупку продуктов, его интерес к этой категории падает (он затарился, у него пропал стимул покупать это снова).
Метод атомарно обновляет быструю оперативную память, а затем сбрасывает новые личные веса и время еды в базу данных симулятора через команду UPSERT (вставка или обновление при конфликте). После этого сессия текущего часа закрывается, а виртуальный поток уничтожается.
1.2. Пошаговое выполнение
- Расчет изменений характера: На основе завершенного сценария аналитическое ядро рассчитывает новые значения личных весов предпочтений \(K\). При покупке или готовке коэффициент категории падает на 15%, при поедании готовой еды — голод сбрасывается в стартовые
0.1000, а вес готовой еды растет на 15%. - Атомарный сдвиг RAM: Новые показатели весов и сброшенный голод записываются в оперативную память (
ConcurrentHashMap), заменяя старый кэш. - Фиксация биологических часов: Формируется SQL-запрос к таблице снапшотов. Симулятор записывает текущий номер часа
current_tickв поле последней еды. - Фиксация весов в СУБД: Формируется SQL-запрос к таблице личных весов. Новые привычки пользователя «запекаются» в постоянную базу данных симулятора.
- Закрытие такт-сессии: Виртуальный поток воркера удаляет сквозной
X-Request-IDиз памяти логирования и успешно завершает работу до следующего вызова.
2. Диаграмма последовательности метода (Вход и Выход флоу)
Диаграмма наглядно показывает, как оркестратор на основе успешно пройденного шага мутирует привычки пользователя в оперативной памяти и выполняет параллельный сброс новых состояний в две таблицы PostgreSQL симулятора.
3. Схемы данных и SQL-взаимодействие
Этот метод выполняет два критически важных UPSERT запроса к внутренней PostgreSQL симулятора для фиксации состояния.
3.1. Сброс биологических часов голода (Запрос к twin_state_snapshots)
Запрос перезаписывает номер текущего часа симуляции (105), обнуляя скаляр голода до сытого состояния:
INSERT INTO simulation.twin_state_snapshots (twin_id, hunger_x0, last_tick_updated, updated_at)
VALUES ('d3b07384-d113-4956-bf8a-e421cd7bf777'::uuid, 0.1000, 105, CURRENT_TIMESTAMP)
ON CONFLICT (twin_id)
DO UPDATE SET
hunger_x0 = EXCLUDED.hunger_x0,
last_tick_updated = EXCLUDED.last_tick_updated,
updated_at = EXCLUDED.updated_at;3.2. Мутация долговременных привычек (Запрос к twin_weight_preferences)
Запрос фиксирует изменение характера покупок твина: из-за того, что он купил фрукты, его интерес к ним падает до 1.0813, снижая частоту закупа на следующих тактах:
INSERT INTO simulation.twin_weight_preferences (twin_id, category_id, preference_weight_k, updated_at)
VALUES ('d3b07384-d113-4956-bf8a-e421cd7bf777'::uuid, 'FRUITS', 1.0813, CURRENT_TIMESTAMP)
ON CONFLICT (twin_id, category_id)
DO UPDATE SET
preference_weight_k = EXCLUDED.preference_weight_k,
updated_at = EXCLUDED.updated_at;4. Спецификация обмена данными (Вход / Выход)
Данные сохраняются во внутренние структуры репозиториев микросервиса.
4.1. Входные параметры фиксации опыта (Входные параметры для метода)
{
"twin_id": "d3b07384-d113-4956-bf8a-e421cd7bf777",
"current_simulation_tick": 105,
"successful_scenario": "SCENARIO_CONSUMING_FOOD"
}4.2. Результат закрытия такт-сессии (Выходные параметры)
{
"committed_twin_id": "d3b07384-d113-4956-bf8a-e421cd7bf777",
"ram_cache_status": "SYNCHRONIZED_WITH_DATABASE",
"database_upsert_status": "ACID_COMMIT_SUCCESS"
}5. ЗАДАЧА ДЛЯ РАЗРАБОТЧИКА: BACKEND
Заголовок: Реализация финального метода фиксации состояния и мутации привычек flush_session_state
5.1. Что нужно сделать
- Написать приватный метод
flushSessionStateвнутри центрального сервиса оркестрацииCoreSimulationEngineImpl. - Реализовать логику пересчета весов: если передан сценарий
CONSUME, вызывать методcontext.preferenceVectorK().put("READY_MEALS", oldWeight * 1.15). Если сценарийBUY, снижать вес купленной категории на 15%. - Выполнить обновление оперативной памяти симулятора через метод
cache.replace(twinId, updatedContext). - Внедрить вызовы репозиториев
SimulationSnapshotRepositoryиTwinWeightPreferencesRepositoryдля трансляции данных в PostgreSQL. - Обеспечить выполнение обоих SQL-запросов
INSERT ... ON CONFLICT DO UPDATEвнутри единой физической транзакции Spring@Transactional(propagation = Propagation.REQUIRED). Если один из запросов падает, вся мутация привычек твина должна быть полностью откачена (Rollback) во избежание рассинхронизации RAM и БД.
6. ЗАДАЧА ДЛЯ РАЗРАБОТЧИКА: МИГРАЦИЯ
Заголовок: Настройка параметров автовакуума (Autovacuum) для таблиц весов и снапшотов в СУБД симулятора
6.1. Что нужно сделать
Поскольку 1500 виртуальных потоков пользователей симулятора на каждом такте будут непрерывно выполнять тяжелые UPDATE/UPSERT запросы к таблицам twin_state_snapshots и twin_weight_preferences, в PostgreSQL симулятора будет скапливаться колоссальное количество «мертвых» строк (Dead Rows/Tuples). Без агрессивной очистки база данных симулятора раздуется и начнет тормозить уже через несколько сотен тактов. Задача миграции — наложить агрессивный профиль очистки автовакуума СУБД на эти две таблицы.
-- Изменения для базы данных симулятора (схема simulation)
-- Запуск очистки таблицы снапшотов при мутации каждых 5% строк
ALTER TABLE simulation.twin_state_snapshots SET (autovacuum_vacuum_scale_factor = 0.05);
ALTER TABLE simulation.twin_state_snapshots SET (autovacuum_analyze_scale_factor = 0.02);
-- Запуск очистки таблицы весов при мутации каждых 5% строк
ALTER TABLE simulation.twin_weight_preferences SET (autovacuum_vacuum_scale_factor = 0.05);
ALTER TABLE simulation.twin_weight_preferences SET (autovacuum_analyze_scale_factor = 0.02);