# 017. Локальное чтение данных T-Bank и фоновая синхронизация **Status:** Accepted — архитектурное направление согласовано. Реализация `persist-tbank-data` добавлена в рабочие ветки приложения; performance/browser и canonical application gates пройдены. Это не отметка развёртывания в production. Ниже сохранён контекст принятия решения, а текущее устройство описывает [модель свежести](../architecture/cross-cutting/data-freshness.md). ## Context Инвестиционная история не сохраняется в БД. Серверные кэши находятся в памяти процесса, а загрузка операций, аналитики дохода и рыночной истории зависит от повторных обращений к T-Bank. Для журнала операций запрос доступных счетов выполняется даже перед чтением кэшированной страницы. Сохранение только ответов без изменения этого пути не устранит ожидание внешнего API. Нужно ускорить все экраны, использующие T-Bank, и уменьшить повторную загрузку данных. Текущие механизмы описаны в [политике свежести](../architecture/cross-cutting/data-freshness.md) и [журнале операций](../domains/operations/overview.md). ## Decision Для уже загруженных данных обычный запрос frontend обслуживается из постоянного локального хранилища без ожидания ответа T-Bank. Обновление выполняется в фоне. Пользователь видит время последнего успешного обновления и может запросить обновление вручную. Сохранённый портфель может ещё не содержать новую сделку; эта задержка принята ради быстрого открытия экрана. Синхронизация запускается только запросами пользовательских экранов и ручным действием «Обновить». Периодических запусков, ежедневного обновления неактивных пользователей и плановой сверки истории нет. Фоновое выполнение означает, что уже запрошенная работа не задерживает выдачу сохранённых данных; самостоятельное расписание обновлений оно не подразумевает. Обычный запрос запускает обновление, только если нужных данных нет либо истёк согласованный срок их свежести: | Данные | Срок свежести | | --- | --- | | Портфель и текущие цены | 1 минута | | Операции текущего месяца | 5 минут | | Список доступных счетов | 5 минут | | Справочник инструментов и календари купонов и дивидендов | 1 сутки | | Незавершённая дневная свеча | 1 минута | Эти сроки проверяются при запросе и не задают расписание фоновых запусков. Аналитика дохода зависит от полноты и свежести исходных операций. Полностью загруженные предыдущие месяцы операций повторно читаются из T-Bank только по кнопке «Обновить» для показанного периода. Обычный запрос догружает отсутствующие интервалы и при необходимости обновляет текущий месяц. Завершённые дневные свечи сохраняются; ручное обновление перечитывает показанный диапазон. Автоматическое обнаружение поздних операций и исправлений в уже полностью загруженных прошлых месяцах не обещается. Кнопка «Обновить» обходит проверку давности и обновляет данные текущего экрана: выбранного счёта, доступных счетов в режиме «Все счета» либо инструмента и показанной личной истории на его странице. Нажатие не означает повторную загрузку всей накопленной истории всех счетов и инструментов. Решение охватывает все экраны с данными T-Bank. Исполненные операции и рыночная история сохраняются; текущие позиции, остатки и цены представлены последним успешно полученным состоянием. Будущие выплаты остаются изменяемым прогнозом, а не исполненными операциями. Это не решение о накоплении исторических снимков стоимости портфеля. Рыночная история бумаг текущего портфеля загружается заранее в рамках запрошенной пользователем работы. Для остальных бумаг первая загрузка начинается при открытии инструмента, результат сохраняется для последующего чтения. Предварительная загрузка истории всего каталога не требуется. При первом подключении текущий портфель и недавние операции могут отображаться до завершения загрузки более ранней истории. Частично загруженный период явно отличается от полного: неполные итоги нельзя выдавать за окончательные, а отсутствие загруженных записей — за подтверждённое отсутствие операций. Смысл полноты определён в [глоссарии](../glossary.md#полнота-истории-счёта). Первый запрос задаёт приоритет: сначала период, нужный экрану, включая периоды сравнения дохода, затем вся доступная история счёта. Уже запущенная догрузка может завершиться после ухода пользователя со страницы; нового периодического запуска это не создаёт. Полнота относится к успешно загруженным временным интервалам. Смена месяца сама по себе не делает завершённым последний неполный интервал прошлого месяца: его оставшаяся часть должна быть догружена. Ошибка промежуточной страницы не подтверждает полноту и не удаляет ранее сохранённые данные. Незавершённая свеча также не становится завершённой только из-за смены дня: её окончательное состояние должен подтвердить источник. Целевой ориентир — до 500 мс для обычного серверного запроса к заполненной БД. Это согласованная цель измерения, а не подтверждённая характеристика системы. Объём данных и набор запросов для проверки предстоит определить. Для этого изменения принято допущение: ID брокерской операции не меняется со временем. Обнаружение сменившихся ID и регулярная сверка старой истории не входят в объём работы. Это допущение проекта, а не гарантия T-Bank: используемый protobuf-контракт допускает изменение ID. Допущение относится к идентичности операции; оно не требует игнорировать новые значения полей, если операция с прежним ID снова получена от брокера. Подключение T-Bank считается постоянным в рассматриваемом сценарии. Архив без подключения, специальная политика хранения после отключения и работа с закрытыми счетами пока не проектируются. Это ограничение объёма не отменяет существующие проверки доступа и обработку ошибок интеграции. ## Alternatives Ожидание свежего ответа T-Bank при каждом открытии экрана сохраняет зависимость скорости и доступности интерфейса от брокера. Увеличение времени жизни кэша в памяти уменьшает часть повторных запросов, но не сохраняет историю после перезапуска и не обеспечивает локальное чтение всех нужных данных. ## Consequences Интерфейсу нужны различимые состояния первичной загрузки, полноты истории, свежести и ошибки фонового обновления. Успешная загрузка недавних операций не подтверждает полноту более ранних периодов или периодов сравнения дохода. Проверки локальной сессии и принадлежности личных данных сохраняются. Способ подтверждения брокерского доступа должен позволять обслужить уже загруженные данные без синхронного ожидания T-Bank. Повторные запросы одного набора данных должны использовать уже выполняющуюся загрузку. Завершённые интервалы и прогресс сохраняются в БД; после перезапуска незавершённый интервал повторяется при следующем запросе или ручном обновлении. Курсор брокера и максимальная дата полученной операции не доказывают полноту. Ручное обновление периода согласует состав операций и их поля с полностью полученным ответом источника. Только успешная загрузка всех страниц позволяет зафиксировать полное покрытие, успешное обновление и удалить отсутствующие в этом ответе записи периода. Ошибка не превращает частичный ответ в полный. Личные операции и позиции сохраняют принадлежность пользователю и счёту. Общие данные инструмента не должны содержать персональные позиции и расчёты; поздний результат прежнего подключения не публикуется для нового подключения. Существующие HTTP-контракты пока не поддерживают все необходимые состояния загрузки и полноты; их изменение входит в будущую реализацию.