docs: explain persisted T-Bank reads and synchronization
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
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.
This commit was merged in pull request #22.
This commit is contained in:
@@ -1,72 +1,66 @@
|
||||
# Свежесть данных и повторное использование
|
||||
|
||||
WealthLedger показывает финансовое наблюдение на момент получения данных.
|
||||
Временный кэш уменьшает повторные обращения к брокеру, но не превращает
|
||||
снимки в историю портфеля и не обещает рыночные данные в реальном времени.
|
||||
WealthLedger читает инвестиционные данные из SQLite. Обычный GET возвращает
|
||||
сохранённый результат и запрашивает фоновые зависимости, если они отсутствуют
|
||||
или устарели. HTTP-ответ не ждёт T-Bank. Модель принята в
|
||||
[ADR 017](../../adr/017-local-tbank-reads-and-background-sync.md).
|
||||
|
||||
## Клиентский и серверный снимки
|
||||
|
||||
[Client Cached Snapshot](../../glossary.md#client-cached-snapshot) — последний
|
||||
успешный ответ, сохранённый TanStack Query в SPA. При обычном фоновом обновлении
|
||||
того же набора данных уже показанный результат остаётся на экране; ошибка
|
||||
обновления сообщает о проблеме, не заменяя известные значения пустотой.
|
||||
Клиентский кэш не является внешней системой или отдельным runtime-приложением.
|
||||
[Client Cached Snapshot](../../glossary.md#client-cached-snapshot) — успешный
|
||||
ответ в TanStack Query. Он сохраняет показанное содержимое при временной ошибке
|
||||
запроса в той же границе доступа. SQLite сохраняет источники независимо от
|
||||
браузера: membership, последний полный portfolio, исполненные операции,
|
||||
общие сведения об инструментах, котировки, свечи и календари.
|
||||
|
||||
[Portfolio Snapshot](../../glossary.md#portfolio-snapshot) — полный результат
|
||||
загрузки портфеля на backend. В пределах разрешённого сценарием срока он может
|
||||
служить серверным fallback при временной ошибке upstream. Backend отмечает
|
||||
такой ответ `isStale`; frontend не выводит это поле из состояния собственного
|
||||
query-кэша. Серверное предупреждение и ошибка клиентского refetch могут
|
||||
возникать независимо.
|
||||
[Полнота периода](../../glossary.md#полнота-истории-счёта) и свежесть различаются.
|
||||
Успешно проверенный пустой интервал полон; последняя страница журнала сама
|
||||
по себе полноту не доказывает. Ошибка сверки сохраняет прежние данные и время.
|
||||
Старый полный портфель не удаляется по истечении TTL. `isStale` показывает
|
||||
возраст portfolio source, а не сам факт неудачного обновления.
|
||||
|
||||
Свежесть и допустимость fallback определяются сценарием. Портфельный fallback
|
||||
не распространяется автоматически на журнал, прогноз событий или страницу
|
||||
инструмента. Точные правила находятся в
|
||||
[справочнике портфеля](../../domains/portfolio/data-reference.md),
|
||||
[журнале операций](../../domains/operations/overview.md) и
|
||||
[будущих событиях](../../domains/income/upcoming-events.md).
|
||||
| Источник | Когда обычный запрос требует обновления |
|
||||
| --- | --- |
|
||||
| Portfolio, котировки, изменяемый хвост дневных свечей | Через 60 секунд |
|
||||
| Membership и изменяемый хвост операций | Через 5 минут |
|
||||
| Metadata, поиск каталога, company и календари | Через сутки |
|
||||
| Полные прошлые интервалы операций и завершённые свечи | При явном обновлении показанного периода |
|
||||
|
||||
По [ADR 007](../../adr/007-react-query-fetch-policy.md) запрос связан с открытием
|
||||
экрана, а возврат фокуса окна не запускает refetch. Повторное открытие после
|
||||
`staleTime` может обновить ответ в фоне. Эта политика не является таймером
|
||||
периодического обновления. Перезапуск backend уничтожает его in-memory
|
||||
снимки и continuations журнала; SQLite не восстанавливает их.
|
||||
TTL не создаёт таймер импорта. Запрошенная работа может закончиться после
|
||||
ухода со страницы. После перезапуска нет автоматического обхода intent:
|
||||
следующий подходящий запрос повторяет незавершённый интервал с первой страницы,
|
||||
переиспользуя полные интервалы. Cursor брокера не служит durable checkpoint.
|
||||
|
||||
Ручное «Обновить» перечитывает зависимости текущего экрана и применённый
|
||||
период независимо от TTL. Повторная сверка полного периода публикуется одной
|
||||
транзакцией после всех страниц, интервалов и счетов, включая `all`.
|
||||
Сбой сохраняет весь прежний результат. Первая загрузка может публиковать
|
||||
полные малые интервалы и показывать частичный период без окончательных сумм.
|
||||
|
||||
Клиент наблюдает только известную активную работу открытого экрана.
|
||||
Status GET и data GET с `sync=observe` не запускают работу. После изменения
|
||||
состояния ответ попадает в ту же query identity; после ухода или завершения
|
||||
наблюдение прекращается. Поздний ответ не заменяет уже принятый новый.
|
||||
[HTTP API](../http-api.md) объясняет envelope и экранный refresh.
|
||||
|
||||
## Смена подключения
|
||||
|
||||
Кэш финансовых данных относится к пользователю, счёту и текущему
|
||||
подключению T-Bank. Backend сначала читает подключение и его generation, затем
|
||||
проверяет возможность повторного использования ответа. Свежий портфель
|
||||
одного счёта не требует нового запроса списка счетов у брокера; при обновлении
|
||||
портфеля доступ проверяется заново. Журнал операций проверяет доступ до чтения
|
||||
кэшированной страницы. Идентификатор счёта и совпадение параметров запроса
|
||||
сами по себе недостаточны для выдачи кэша.
|
||||
Каждое чтение проверяет локальную сессию, текущее подключение, известный отказ
|
||||
токена и сохранённый состав доступных счетов. Расшифровка token и GetAccounts
|
||||
для локальной выдачи не нужны. Старый membership допускает выдачу и фоновую
|
||||
сверку; это задержка обнаружения отзыва доступа, а не live-проверка брокера.
|
||||
Unknown membership не даёт доступа к произвольному accountId: ответ сообщает
|
||||
о загрузке доступа. Успешный новый список немедленно ограничивает последующие
|
||||
чтения. Известный invalid token блокирует личные данные.
|
||||
|
||||
При каждом успешном сохранении подключения token шифруется с новым
|
||||
AES-GCM nonce. Из сохранённого шифротекста backend вычисляет непрозрачную
|
||||
внутреннюю generation. Она не хранится отдельным полем базы и не входит
|
||||
в API, журналы или ошибки. Portfolio Snapshot и Ledger Page Cache допускают
|
||||
повторное использование только в пределах соответствующей generation.
|
||||
Старый кэш или поздно завершившийся запрос прежней generation не обслуживает
|
||||
новый запрос после замены подключения, включая сохранение того же plaintext
|
||||
token. Удаление подключения не оставляет доступного контекста для чтения кэша.
|
||||
Успешный PUT атомарно сохраняет token, новую случайную внутреннюю revision
|
||||
и membership из проверки token. Прежние личные datasets и work становятся
|
||||
недоступны. DELETE удаляет подключение и личные данные; общие неперсональные
|
||||
источники могут оставаться. Неуспешный PUT сохраняет действующую границу.
|
||||
|
||||
После успешного изменения подключения frontend сначала записывает
|
||||
подтверждённый status, затем сбрасывает generated GET queries в поддеревьях
|
||||
`/api/v1/brokerage-accounts`, `/api/v1/stocks` и `/api/v1/bonds`. Активные
|
||||
выборки запрашиваются заново, неактивные — при следующем использовании.
|
||||
Client Cached Snapshot прежнего подключения больше не служит результатом
|
||||
новой границы.
|
||||
|
||||
Неуспешная операция подключения не меняет статус, generation и доступные
|
||||
финансовые данные. Обычная ошибка refetch также сохраняет клиентский снимок
|
||||
текущей границы. Logout — отдельное событие: оно очищает состояние
|
||||
пользовательской сессии, status подключения и query cache.
|
||||
|
||||
Пользовательский сценарий описан в [интеграции T-Bank](../../integrations/tbank.md).
|
||||
Согласованные правила frontend находятся в workspace-спецификациях
|
||||
[query coherence](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/frontend-query-coherence/spec.md)
|
||||
и [data resilience](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/frontend-data-resilience/spec.md);
|
||||
серверные правила — в
|
||||
[portfolio](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/portfolio-view/spec.md) и
|
||||
[ledger](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/brokerage-account-ledger/spec.md).
|
||||
Публикация проверяет revision и attempt в той же SQLite-транзакции; поздняя
|
||||
работа старого подключения не меняет даже timestamp. Revision не попадает
|
||||
в API, логи или cursor. Frontend очищает personal queries при смене подключения
|
||||
и известном отказе доступа; поздний ответ не восстанавливает скрытые данные.
|
||||
Logout очищает сессию и query cache. Подробнее —
|
||||
[интеграция T-Bank](../../integrations/tbank.md).
|
||||
|
||||
@@ -22,6 +22,18 @@
|
||||
портфеля остаётся доступным после ошибки refetch; сообщение и повтор
|
||||
относятся к обновлению, а не к отсутствию инвестиций.
|
||||
|
||||
Серверная полнота не выводится из query lifecycle. Missing показывает
|
||||
skeleton только отсутствующих секций, partial — подтверждённые строки и
|
||||
сообщение о неполноте. Totals ждут обязательных зависимостей, comparisons
|
||||
готовятся независимо. Только complete empty означает отсутствие операций.
|
||||
Время источника не заменяется временем получения HTTP-ответа.
|
||||
|
||||
Ручное обновление сохраняет показанный результат и applied filters; кнопка
|
||||
недоступна во время уже запрошенной работы. Ошибка transport отличается от
|
||||
ошибки source work. Status observation прекращается после terminal outcome
|
||||
или ухода; само истечение TTL не запускает импорт. Известный access loss
|
||||
очищает personal view, включая защиту от позднего ответа.
|
||||
|
||||
## Известная ошибка сценария
|
||||
|
||||
Ошибки счетов, портфеля и подключения T-Bank остаются локальными: рядом
|
||||
|
||||
Reference in New Issue
Block a user