Files
docs/adr/017-local-tbank-reads-and-background-sync.md
T
ksv741 07de062ebb
Conventional commits / commits (pull_request) Successful in 14s
Docs security / security (pull_request) Successful in 8s
Docs verify / verify (pull_request) Successful in 13s
Docs security / security (push) Successful in 8s
Docs verify / verify (push) Successful in 12s
docs: explain persisted T-Bank reads and synchronization
Document local data ownership, coverage and freshness, refresh behavior, failure
recovery and additive migration rollback. Record ADR 017.
2026-09-26 21:22:50 +03:00

13 KiB

017. Локальное чтение данных T-Bank и фоновая синхронизация

Status: Accepted — архитектурное направление согласовано.

Реализация persist-tbank-data добавлена в рабочие ветки приложения; performance/browser и canonical application gates пройдены. Это не отметка развёртывания в production. Ниже сохранён контекст принятия решения, а текущее устройство описывает модель свежести.

Context

Инвестиционная история не сохраняется в БД. Серверные кэши находятся в памяти процесса, а загрузка операций, аналитики дохода и рыночной истории зависит от повторных обращений к T-Bank. Для журнала операций запрос доступных счетов выполняется даже перед чтением кэшированной страницы. Сохранение только ответов без изменения этого пути не устранит ожидание внешнего API.

Нужно ускорить все экраны, использующие T-Bank, и уменьшить повторную загрузку данных. Текущие механизмы описаны в политике свежести и журнале операций.

Decision

Для уже загруженных данных обычный запрос frontend обслуживается из постоянного локального хранилища без ожидания ответа T-Bank. Обновление выполняется в фоне. Пользователь видит время последнего успешного обновления и может запросить обновление вручную. Сохранённый портфель может ещё не содержать новую сделку; эта задержка принята ради быстрого открытия экрана.

Синхронизация запускается только запросами пользовательских экранов и ручным действием «Обновить». Периодических запусков, ежедневного обновления неактивных пользователей и плановой сверки истории нет. Фоновое выполнение означает, что уже запрошенная работа не задерживает выдачу сохранённых данных; самостоятельное расписание обновлений оно не подразумевает.

Обычный запрос запускает обновление, только если нужных данных нет либо истёк согласованный срок их свежести:

Данные Срок свежести
Портфель и текущие цены 1 минута
Операции текущего месяца 5 минут
Список доступных счетов 5 минут
Справочник инструментов и календари купонов и дивидендов 1 сутки
Незавершённая дневная свеча 1 минута

Эти сроки проверяются при запросе и не задают расписание фоновых запусков. Аналитика дохода зависит от полноты и свежести исходных операций.

Полностью загруженные предыдущие месяцы операций повторно читаются из T-Bank только по кнопке «Обновить» для показанного периода. Обычный запрос догружает отсутствующие интервалы и при необходимости обновляет текущий месяц. Завершённые дневные свечи сохраняются; ручное обновление перечитывает показанный диапазон. Автоматическое обнаружение поздних операций и исправлений в уже полностью загруженных прошлых месяцах не обещается.

Кнопка «Обновить» обходит проверку давности и обновляет данные текущего экрана: выбранного счёта, доступных счетов в режиме «Все счета» либо инструмента и показанной личной истории на его странице. Нажатие не означает повторную загрузку всей накопленной истории всех счетов и инструментов.

Решение охватывает все экраны с данными T-Bank. Исполненные операции и рыночная история сохраняются; текущие позиции, остатки и цены представлены последним успешно полученным состоянием. Будущие выплаты остаются изменяемым прогнозом, а не исполненными операциями. Это не решение о накоплении исторических снимков стоимости портфеля.

Рыночная история бумаг текущего портфеля загружается заранее в рамках запрошенной пользователем работы. Для остальных бумаг первая загрузка начинается при открытии инструмента, результат сохраняется для последующего чтения. Предварительная загрузка истории всего каталога не требуется.

При первом подключении текущий портфель и недавние операции могут отображаться до завершения загрузки более ранней истории. Частично загруженный период явно отличается от полного: неполные итоги нельзя выдавать за окончательные, а отсутствие загруженных записей — за подтверждённое отсутствие операций. Смысл полноты определён в глоссарии.

Первый запрос задаёт приоритет: сначала период, нужный экрану, включая периоды сравнения дохода, затем вся доступная история счёта. Уже запущенная догрузка может завершиться после ухода пользователя со страницы; нового периодического запуска это не создаёт.

Полнота относится к успешно загруженным временным интервалам. Смена месяца сама по себе не делает завершённым последний неполный интервал прошлого месяца: его оставшаяся часть должна быть догружена. Ошибка промежуточной страницы не подтверждает полноту и не удаляет ранее сохранённые данные. Незавершённая свеча также не становится завершённой только из-за смены дня: её окончательное состояние должен подтвердить источник.

Целевой ориентир — до 500 мс для обычного серверного запроса к заполненной БД. Это согласованная цель измерения, а не подтверждённая характеристика системы. Объём данных и набор запросов для проверки предстоит определить.

Для этого изменения принято допущение: ID брокерской операции не меняется со временем. Обнаружение сменившихся ID и регулярная сверка старой истории не входят в объём работы. Это допущение проекта, а не гарантия T-Bank: используемый protobuf-контракт допускает изменение ID. Допущение относится к идентичности операции; оно не требует игнорировать новые значения полей, если операция с прежним ID снова получена от брокера.

Подключение T-Bank считается постоянным в рассматриваемом сценарии. Архив без подключения, специальная политика хранения после отключения и работа с закрытыми счетами пока не проектируются. Это ограничение объёма не отменяет существующие проверки доступа и обработку ошибок интеграции.

Alternatives

Ожидание свежего ответа T-Bank при каждом открытии экрана сохраняет зависимость скорости и доступности интерфейса от брокера. Увеличение времени жизни кэша в памяти уменьшает часть повторных запросов, но не сохраняет историю после перезапуска и не обеспечивает локальное чтение всех нужных данных.

Consequences

Интерфейсу нужны различимые состояния первичной загрузки, полноты истории, свежести и ошибки фонового обновления. Успешная загрузка недавних операций не подтверждает полноту более ранних периодов или периодов сравнения дохода.

Проверки локальной сессии и принадлежности личных данных сохраняются. Способ подтверждения брокерского доступа должен позволять обслужить уже загруженные данные без синхронного ожидания T-Bank.

Повторные запросы одного набора данных должны использовать уже выполняющуюся загрузку. Завершённые интервалы и прогресс сохраняются в БД; после перезапуска незавершённый интервал повторяется при следующем запросе или ручном обновлении. Курсор брокера и максимальная дата полученной операции не доказывают полноту.

Ручное обновление периода согласует состав операций и их поля с полностью полученным ответом источника. Только успешная загрузка всех страниц позволяет зафиксировать полное покрытие, успешное обновление и удалить отсутствующие в этом ответе записи периода. Ошибка не превращает частичный ответ в полный.

Личные операции и позиции сохраняют принадлежность пользователю и счёту. Общие данные инструмента не должны содержать персональные позиции и расчёты; поздний результат прежнего подключения не публикуется для нового подключения.

Существующие HTTP-контракты пока не поддерживают все необходимые состояния загрузки и полноты; их изменение входит в будущую реализацию.