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
Document local data ownership, coverage and freshness, refresh behavior, failure recovery and additive migration rollback. Record ADR 017.
141 lines
13 KiB
Markdown
141 lines
13 KiB
Markdown
# 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-контракты пока не поддерживают все необходимые состояния
|
|
загрузки и полноты; их изменение входит в будущую реализацию.
|