Files
docs/architecture/cross-cutting/data-freshness.md
T
ksv741 f0cab445d7
Docs security / security (push) Successful in 46s
Docs verify / verify (push) Successful in 13s
docs: document hourly investment reads
2026-10-09 21:13:45 +03:00

8.1 KiB

Свежесть данных и повторное использование

WealthLedger читает личные инвестиционные данные из SQLite. Обычный GET и его HTTP retry возвращают сохранённый результат и не запускают личную работу с T-Bank. Нормальным владельцем обновления служит часовой обход текущего подключения: после успешного подключения он начинает первую попытку, затем начинает следующую не ранее чем через 60 минут от начала предыдущей. После простоя выполняется не более одна актуальная попытка, а перекрывающийся срок пропускается, не ставится в очередь. Общие справочные данные инструментов запрашиваются онлайн, когда это требуется карточке; финансовый HTTP-ответ не ждёт T-Bank. Модель принята в ADR 019.

Клиентский и серверный снимки

Client Cached Snapshot — успешный ответ в TanStack Query. Он сохраняет показанное содержимое при временной ошибке HTTP-перечитывания в той же границе доступа. Это не серверный fallback и не состояние часового обхода. SQLite независимо от браузера хранит membership, последний полный portfolio, исполненные операции, прогнозы, общие сведения об инструментах, котировки, свечи и календари.

Полнота периода и свежесть различаются. Успешно проверенный пустой результат полон и доступен; последняя страница журнала сама по себе полноту не доказывает. Результат каждого личного ресурса в { data, meta } описывают пять независимых значений: freshness, completeness, lastSuccessfulAt, lastAttempt и availability. Первые, полнота и lastSuccessfulAt относятся только к возвращённому подтверждённому результату. lastAttempt описывает относящуюся к ресурсу часовую попытку: none, running, succeeded, partial или failed.

Поздняя неуспешная или частичная попытка сохраняет прежний полный результат и его исходное время. Если полного результата нет, data равно null: состояние availability объясняет первоначальную загрузку, временную недоступность либо недоступность подключения. Пустой массив не означает отсутствие результата. Старый полный portfolio не удаляется из-за возраста. Portfolio.isStale сохраняет смысл возраста его snapshot, а не обозначает неуспех обхода или клиентскую ошибку перечитывания.

Источник Владелец нормального обновления
Membership, portfolio, изменяемый хвост операций и события Часовой обход текущего подключения
Котировки и изменяемый хвост дневных свечей Установленная политика источника; не ordinary personal GET
Metadata, поиск каталога и company Онлайн при чтении
Полные прошлые интервалы операций и завершённые свечи Не обновляются часовым обходом или обычным GET

Два исключения разрешают только первое получение отсутствующего результата: первое открытие неподтверждённого исторического интервала операций получает только этот интервал и возвращает локальные строки с неполным покрытием; первое открытие диапазона свечей без подтверждённого локального результата получает только этот диапазон. Ни одно исключение не обновляет membership, portfolio, события, другой интервал или диапазон. Их HTTP retry также только перечитывает локальное состояние. Подтверждённый полный интервал или диапазон остаётся локальным.

Часовой обход сохраняет успешные разделы независимо, а failed section не заменяет прежний complete result. Отменой query lifecycle владеет TanStack Query. Открытый экран перечитывает ресурс не чаще одного раза в 30 минут; это локальный HTTP read. Совместимый параметр sync=observe, пока он есть в маршруте, также является только чтением и не представляет команду обходу. HTTP API описывает исполняемый контракт envelope.

Смена подключения

Каждое чтение проверяет локальную сессию, текущее подключение, известный отказ токена и сохранённый состав доступных счетов. Расшифровка token и GetAccounts для локальной выдачи не нужны. Старый membership допускает выдачу и фоновую сверку; это задержка обнаружения отзыва доступа, а не live-проверка брокера. Unknown membership не даёт доступа к произвольному accountId: ответ сообщает о загрузке доступа. Успешный новый список немедленно ограничивает последующие чтения. Известный invalid token блокирует личные данные.

Успешный PUT атомарно сохраняет token, новую случайную внутреннюю revision и membership из проверки token. Прежние личные datasets и work становятся недоступны. DELETE удаляет подключение и личные данные; общие неперсональные источники могут оставаться. Неуспешный PUT сохраняет действующую границу.

Публикация проверяет revision и attempt в той же SQLite-транзакции; поздняя работа старого подключения не меняет даже timestamp. Revision не попадает в API, логи или cursor. Frontend очищает personal queries при смене подключения и известном отказе доступа; поздний ответ не восстанавливает скрытые данные. Logout очищает сессию и query cache. Подробнее — интеграция T-Bank.