docs: document hourly investment reads #32
@@ -1,6 +1,8 @@
|
||||
# 017. Локальное чтение данных T-Bank и фоновая синхронизация
|
||||
|
||||
**Status:** Accepted — архитектурное направление согласовано.
|
||||
**Status:** Accepted — историческое архитектурное направление. Решения ниже о
|
||||
request-driven запуске, ручном обновлении и отсутствии периодического обхода
|
||||
заменены [ADR 019](019-hourly-reads-and-online-instrument-reference.md).
|
||||
|
||||
Prefetch policy ниже заменена [ADR 018](018-minimal-runtime-coordination.md):
|
||||
свечи загружаются по запрошенному диапазону, без предварительной загрузки
|
||||
|
||||
@@ -1,25 +1,37 @@
|
||||
# 019. Часовой обход и онлайн-справочник инструментов
|
||||
|
||||
**Status:** Accepted. Дополняет [ADR 017](017-local-tbank-reads-and-background-sync.md)
|
||||
и [ADR 018](018-minimal-runtime-coordination.md).
|
||||
**Status:** Accepted. Заменяет request-driven, manual-refresh и
|
||||
no-periodic-walk части [ADR 017](017-local-tbank-reads-and-background-sync.md)
|
||||
и дополняет [ADR 018](018-minimal-runtime-coordination.md).
|
||||
|
||||
## Decision
|
||||
|
||||
- Личные T-Bank данные обновляются владельцами источников через durable hourly
|
||||
walk; обычные GET не запускают screen import.
|
||||
- Quotes, candles, operations, forecasts и события сохраняют собственные
|
||||
локальные состояния и время последнего успешного чтения.
|
||||
- Личные T-Bank данные текущего подключения обновляются владельцами источников
|
||||
через durable hourly walk; его результат ограничен этой connection boundary.
|
||||
Обычный GET и retry читают только сохранённый результат и не запускают
|
||||
personal work.
|
||||
- Только первое открытие неподтверждённого исторического интервала operations
|
||||
и первого неоткрытого диапазона candles может получить соответственно этот
|
||||
интервал или диапазон. Это не manual sync; повторное чтение не расширяет и не
|
||||
запускает такую работу заново.
|
||||
- Portfolio, operations, forecasts и события сохраняют собственные complete
|
||||
результаты и время последнего успешного чтения. Результат ресурса
|
||||
(freshness, completeness, `lastSuccessfulAt`, availability) независим от
|
||||
resource-relevant последней часовой попытки: поздняя partial/failed попытка
|
||||
не заменяет сохранённый complete result. При его отсутствии `data: null`.
|
||||
- Detail, company, catalog search и ticker lookup получают ответ онлайн через
|
||||
существующие integration clients. Их ошибки не заменяют сохранённые
|
||||
финансовые данные или подписи snapshot.
|
||||
- Старые справочные строки не являются источником актуальности и удаляются
|
||||
только отдельной совместимой миграцией после проверки FK и свечей.
|
||||
- Клиент повторяет открытые инвестиционные GET не чаще одного раза в 30 минут;
|
||||
retry повторяет чтение и не создаёт screen sync work.
|
||||
retry повторяет чтение и не создаёт screen sync work. Наблюдение последней
|
||||
попытки, включая Accounts `sync`, не является командой.
|
||||
|
||||
## Consequences
|
||||
|
||||
Карточки инструментов зависят от доступности публичного upstream в момент
|
||||
чтения. Финансовые экраны сохраняют последний успешный snapshot, а статус
|
||||
последнего hourly walk показывается отдельно. OpenAPI backend остаётся единственным
|
||||
источником HTTP-контракта; frontend использует опубликованный snapshot.
|
||||
последнего hourly walk показывается отдельно. OpenAPI backend остаётся
|
||||
единственным исполняемым источником HTTP-контракта; frontend использует
|
||||
опубликованный snapshot.
|
||||
|
||||
@@ -1,54 +1,64 @@
|
||||
# Свежесть данных и повторное использование
|
||||
|
||||
WealthLedger читает инвестиционные данные из SQLite. Обычный GET возвращает
|
||||
сохранённый результат и не запускает личную синхронизацию. Общие справочные
|
||||
данные инструментов запрашиваются онлайн, когда это требуется карточке;
|
||||
финансовый HTTP-ответ не ждёт T-Bank. Модель принята в
|
||||
[ADR 017](../../adr/017-local-tbank-reads-and-background-sync.md).
|
||||
WealthLedger читает личные инвестиционные данные из SQLite. Обычный GET и его
|
||||
HTTP retry возвращают сохранённый результат и не запускают личную работу с
|
||||
T-Bank. Нормальным владельцем обновления служит часовой обход текущего
|
||||
подключения: после успешного подключения он начинает первую попытку, затем
|
||||
начинает следующую не ранее чем через 60 минут от начала предыдущей. После
|
||||
простоя выполняется не более одна актуальная попытка, а перекрывающийся срок
|
||||
пропускается, не ставится в очередь. Общие справочные данные инструментов
|
||||
запрашиваются онлайн, когда это требуется карточке; финансовый HTTP-ответ не
|
||||
ждёт T-Bank. Модель принята в
|
||||
[ADR 019](../../adr/019-hourly-reads-and-online-instrument-reference.md).
|
||||
|
||||
## Клиентский и серверный снимки
|
||||
|
||||
[Client Cached Snapshot](../../glossary.md#client-cached-snapshot) — успешный
|
||||
ответ в TanStack Query. Он сохраняет показанное содержимое при временной ошибке
|
||||
запроса в той же границе доступа. SQLite сохраняет источники независимо от
|
||||
браузера: membership, последний полный portfolio, исполненные операции,
|
||||
общие сведения об инструментах, котировки, свечи и календари.
|
||||
HTTP-перечитывания в той же границе доступа. Это не серверный fallback и не
|
||||
состояние часового обхода. SQLite независимо от браузера хранит membership,
|
||||
последний полный portfolio, исполненные операции, прогнозы, общие сведения об
|
||||
инструментах, котировки, свечи и календари.
|
||||
|
||||
[Полнота периода](../../glossary.md#полнота-истории-счёта) и свежесть различаются.
|
||||
Успешно проверенный пустой интервал полон; последняя страница журнала сама
|
||||
по себе полноту не доказывает. Ошибка сверки сохраняет прежние данные и время.
|
||||
Старый полный портфель не удаляется по истечении TTL. `isStale` показывает
|
||||
возраст portfolio source, а не сам факт неудачного обновления.
|
||||
Успешно проверенный пустой результат полон и доступен; последняя страница
|
||||
журнала сама по себе полноту не доказывает. Результат каждого личного ресурса
|
||||
в `{ data, meta }` описывают пять независимых значений: freshness,
|
||||
completeness, `lastSuccessfulAt`, `lastAttempt` и availability. Первые,
|
||||
полнота и `lastSuccessfulAt` относятся только к возвращённому подтверждённому
|
||||
результату. `lastAttempt` описывает относящуюся к ресурсу часовую попытку:
|
||||
`none`, `running`, `succeeded`, `partial` или `failed`.
|
||||
|
||||
| Источник | Когда обычный запрос требует обновления |
|
||||
Поздняя неуспешная или частичная попытка сохраняет прежний полный результат и
|
||||
его исходное время. Если полного результата нет, `data` равно `null`: состояние
|
||||
availability объясняет первоначальную загрузку, временную недоступность либо
|
||||
недоступность подключения. Пустой массив не означает отсутствие результата.
|
||||
Старый полный portfolio не удаляется из-за возраста. `Portfolio.isStale`
|
||||
сохраняет смысл возраста его snapshot, а не обозначает неуспех обхода или
|
||||
клиентскую ошибку перечитывания.
|
||||
|
||||
| Источник | Владелец нормального обновления |
|
||||
| --- | --- |
|
||||
| Portfolio, котировки, изменяемый хвост дневных свечей | Через 60 секунд |
|
||||
| Membership и изменяемый хвост операций | Через 5 минут |
|
||||
| Membership, portfolio, изменяемый хвост операций и события | Часовой обход текущего подключения |
|
||||
| Котировки и изменяемый хвост дневных свечей | Установленная политика источника; не ordinary personal GET |
|
||||
| Metadata, поиск каталога и company | Онлайн при чтении |
|
||||
| Календари | Через часовой обход |
|
||||
| Полные прошлые интервалы операций и завершённые свечи | При явном обновлении показанного периода |
|
||||
| Полные прошлые интервалы операций и завершённые свечи | Не обновляются часовым обходом или обычным GET |
|
||||
|
||||
TTL не создаёт таймер импорта. Запрошенная работа может закончиться после
|
||||
ухода со страницы. После перезапуска нет автоматического обхода intent:
|
||||
следующий подходящий запрос повторяет незавершённый интервал с первой страницы,
|
||||
переиспользуя полные интервалы. Cursor брокера не служит durable checkpoint.
|
||||
Два исключения разрешают только первое получение отсутствующего результата:
|
||||
первое открытие неподтверждённого исторического интервала операций получает
|
||||
только этот интервал и возвращает локальные строки с неполным покрытием; первое
|
||||
открытие диапазона свечей без подтверждённого локального результата получает
|
||||
только этот диапазон. Ни одно исключение не обновляет membership, portfolio,
|
||||
события, другой интервал или диапазон. Их HTTP retry также только перечитывает
|
||||
локальное состояние. Подтверждённый полный интервал или диапазон остаётся
|
||||
локальным.
|
||||
|
||||
Повторное чтение перечитывает общие справочные данные онлайн, а финансовые
|
||||
ресурсы используют сохранённый результат и применяемую политику свежести.
|
||||
Повторная сверка полного периода публикуется одной
|
||||
транзакцией после всех страниц, интервалов и счетов, включая `all`.
|
||||
Сбой сохраняет весь прежний результат. Первая загрузка может публиковать
|
||||
полные малые интервалы и показывать частичный период без окончательных сумм.
|
||||
|
||||
Клиент наблюдает только известную активную работу открытого экрана.
|
||||
Status GET и data GET с `sync=observe` не запускают работу. После изменения
|
||||
состояния ответ попадает в ту же query identity; после ухода или завершения
|
||||
наблюдение прекращается. Поздний ответ не заменяет уже принятый новый.
|
||||
[HTTP API](../http-api.md) объясняет envelope и экранный refresh.
|
||||
|
||||
Отменой query lifecycle владеет TanStack Query. Status не пересобирает
|
||||
финансовые ответы и не передаёт hash notifications. Свечи нового диапазона
|
||||
загружаются при его открытии; предзагрузка всей истории портфеля не выполняется.
|
||||
Часовой обход сохраняет успешные разделы независимо, а failed section не
|
||||
заменяет прежний complete result. Отменой query lifecycle владеет TanStack
|
||||
Query. Открытый экран перечитывает ресурс не чаще одного раза в 30 минут;
|
||||
это локальный HTTP read. Совместимый параметр `sync=observe`, пока он есть в
|
||||
маршруте, также является только чтением и не представляет команду обходу.
|
||||
[HTTP API](../http-api.md) описывает исполняемый контракт envelope.
|
||||
|
||||
## Смена подключения
|
||||
|
||||
|
||||
+21
-20
@@ -2,7 +2,8 @@
|
||||
|
||||
## Источник контракта
|
||||
|
||||
Backend генерирует OpenAPI из собственного публичного API. Frontend использует
|
||||
Backend генерирует OpenAPI из собственного публичного API. Этот сгенерированный
|
||||
OpenAPI — исполняемый источник HTTP-контракта. Frontend использует
|
||||
предоставленный OpenAPI snapshot как актуальный вход и локально генерирует
|
||||
типизированный клиент. Backend владеет контрактом, а подготовка и доставка
|
||||
схемы находятся вне frontend. Это разделение принято в
|
||||
@@ -22,27 +23,27 @@ environment policy, а не используется frontend в runtime.
|
||||
|
||||
## Инвестиционные данные и синхронизация
|
||||
|
||||
T-Bank data GET возвращают envelope `{ data, meta }`. `data` может быть `null`
|
||||
при missing или неполном финансовом агрегате; partial ledger/candles могут
|
||||
содержать подтверждённые строки. `meta` разделяет availability, freshness,
|
||||
lastSuccessfulAt, sync, coverage и состояния зависимостей. `dataRevision`
|
||||
описывает набор данных; пустое завершённое покрытие явно представлено в coverage.
|
||||
Публичной hash-версии состояния нет. Ни одно поле не раскрывает connection revision.
|
||||
Затронутые GET инвестиционных ресурсов возвращают сгенерированный contract
|
||||
`{ data, meta }`. `data` nullable: `null` означает отсутствие complete result,
|
||||
а подтверждённый пустой массив является available complete result. `meta`
|
||||
независимо описывает freshness, completeness, `lastSuccessfulAt`,
|
||||
resource-relevant `lastAttempt` и availability. `lastAttempt` имеет состояния
|
||||
`none`, `running`, `succeeded`, `partial` и `failed`; его неуспех не заменяет
|
||||
сохранённый complete result или его время. `Portfolio.isStale` остаётся
|
||||
специфичным для snapshot полем, а не заменой состояния попытки.
|
||||
|
||||
Обычный GET планирует missing/stale зависимости после проверки доступа.
|
||||
GET с `sync=observe` только читает. `POST /api/v1/tbank-sync` принимает
|
||||
валидированный screen descriptor и возвращает `202` с handle и нормализованным
|
||||
scope. `GET /api/v1/tbank-sync/:id` наблюдает разрешённую работу; чужой или
|
||||
прежний handle возвращает `404`. Приём работы не означает её успех.
|
||||
Только Accounts дополнительно возвращает top-level `sync`: `null`, если у
|
||||
текущего подключения ещё не было часовой попытки, иначе connection-wide
|
||||
наблюдаемый результат. Это наблюдение, не команда. Обычный GET и retry после
|
||||
проверки доступа читают локальное состояние и не начинают личную работу.
|
||||
Устаревший `sync=observe`, пока он сохранён для совместимости маршрута, также
|
||||
только читает. Request-started screen-sync command/status не является текущей
|
||||
AS-IS моделью.
|
||||
|
||||
Status возвращает state/errorCode без данных ресурсов и численных progress
|
||||
counters. Клиент перечитывает показанные resources через `sync=observe` во время
|
||||
работы и после завершения, сохраняя generated query identity. Sync states ресурса:
|
||||
`idle`, `running`, `failed`; отдельного публичного `queued` нет.
|
||||
|
||||
Source failure принятой работы передаётся безопасным `meta.sync.errorCode`;
|
||||
HTTP transport/access/input errors сохраняют Problem Details. Старые данные
|
||||
при transient failure сохраняют исходное успешное время. Детали поведения —
|
||||
Безопасные ошибки завершённой часовой попытки передаются в `lastAttempt` и
|
||||
Accounts `sync`; HTTP transport/access/input errors сохраняют Problem Details.
|
||||
Старые данные при временной source failure сохраняют исходное успешное время.
|
||||
Ни одно поле не раскрывает connection revision. Детали поведения —
|
||||
[свежесть и полнота](cross-cutting/data-freshness.md).
|
||||
|
||||
Envelope несовместим с прежними bare-array ответами: backend/frontend
|
||||
|
||||
@@ -40,10 +40,10 @@
|
||||
## Период и список
|
||||
|
||||
Без фильтра период начинается сегодня в UTC и заканчивается через 30 дней
|
||||
после начала, обе даты включены. Поля «С» и «По» позволяют изменить период:
|
||||
«Применить» сохраняет выбранные календарные даты в URL и запрашивает результат,
|
||||
«Сбросить» возвращает период по умолчанию. Обзор счёта сохраняет прогноз
|
||||
на текущую дату и следующие 30 дней.
|
||||
после начала, обе даты включены. `from` и `to` принимают только строгие даты
|
||||
`YYYY-MM-DD`; без `from` используется текущая дата UTC, без `to` — `from + 30`
|
||||
календарных дней. Поля «С» и «По» сохраняют выбранные календарные даты в URL,
|
||||
а «Сбросить» возвращает период по умолчанию.
|
||||
|
||||
События упорядочены по календарной дате. У каждой строки видны тип,
|
||||
инструмент, дата и доступная сумма в исходной валюте. Список не имеет
|
||||
@@ -52,10 +52,13 @@
|
||||
отсутствия всех будущих выплат. Инструмент без поддерживаемых данных
|
||||
не получает искусственную строку «нет данных».
|
||||
|
||||
API принимает необязательные `from` и `to` в формате `YYYY-MM-DD` для
|
||||
отдельного и общего счёта. Без `from` используется сегодня в UTC,
|
||||
без `to` — 30 дней после начала. Неверный формат или несуществующая дата
|
||||
дают `400`; обратный период — `400 INVALID_EVENTS_PERIOD`.
|
||||
Сохранённый forecast сохраняет свой `calculatedAt` и исходное включительное
|
||||
окно. GET для отдельного счёта или `all` возвращает только пересечение этого
|
||||
окна и запрошенного UTC-периода, не меняя ни `calculatedAt`, ни исходное окно.
|
||||
Пустое пересечение или отсутствие событий в пересечении — успешный пустой
|
||||
список с теми же metadata; это не отсутствие forecast. Неверный формат или
|
||||
несуществующая дата дают `400`; обратный период — `400 INVALID_EVENTS_PERIOD`
|
||||
без замены периода и без запуска личной работы.
|
||||
Фильтрация на сервере предшествует сортировке и вычислению
|
||||
`incomeTotalsByCurrency`, включающего только купоны и дивиденды.
|
||||
Итоги остаются в ответе API; полный экран показывает список без общего итога.
|
||||
@@ -63,26 +66,30 @@ API принимает необязательные `from` и `to` в форма
|
||||
## Получение и отказы
|
||||
|
||||
Запрос требует сессии, подключения и локально подтверждённого membership.
|
||||
Прогноз строится из личного сохранённого portfolio и общих календарей: T-Bank для
|
||||
дивидендов, MOEX для bond events. Отдельного синхронного получения portfolio
|
||||
нет. Личные оценки сохраняются отдельно от общих календарей.
|
||||
Он читает сохранённый forecast и не запускает личную синхронизацию. Часовой
|
||||
обход строит forecast из полного личного portfolio и общих календарей: T-Bank
|
||||
для дивидендов, MOEX для bond events. Личные оценки сохраняются отдельно от
|
||||
общих календарей.
|
||||
|
||||
Последний полный forecast привязан к scope, периоду и membership.
|
||||
Если новый portfolio требует ещё недоступного календаря, прежний полный
|
||||
прогноз и его source times остаются, в том числе после рестарта. Новый
|
||||
полный результат заменяет его атомарно. Без fallback показывается
|
||||
missing/partial, а не подтверждённое отсутствие выплат. Другой период или
|
||||
изменившийся membership не получают старый прогноз под новым названием.
|
||||
Source failure сообщается в metadata и не изменяет успешное время.
|
||||
Последний полный forecast привязан к scope, исходному окну и membership. Если
|
||||
часовой обход не может получить полный новый forecast, прежний полный прогноз,
|
||||
его `calculatedAt` и исходное окно остаются читаемыми, в том числе после
|
||||
рестарта; `meta.lastAttempt` отдельно сообщает об ошибке обновления. Без
|
||||
полного forecast `data: null` и metadata обозначает initial loading либо
|
||||
временную недоступность, а не подтверждённое отсутствие выплат. В режиме `all`
|
||||
результат complete только при полном вкладе каждого включённого счёта. Другой
|
||||
scope или изменившийся membership не получают старый forecast под новым
|
||||
названием.
|
||||
Успешный ответ MOEX без запрошенного блока означает отсутствие поддерживаемых
|
||||
событий этого источника; это отличается от transport failure и повреждённого
|
||||
формата ответа.
|
||||
|
||||
При первом открытии показан каркас заголовка и строк, без интерактивных
|
||||
заглушек. Пустой ответ сохраняет возможность изменить период.
|
||||
При обычном фоновом обновлении уже полученные данные остаются на экране,
|
||||
ошибка получает предупреждение и повторную попытку. Без выбранного счёта
|
||||
запрос не выполняется. Смена сессии и подключения следует
|
||||
При первом открытии без complete forecast показан каркас заголовка и строк,
|
||||
без интерактивных заглушек. Пустой успешный ответ сохраняет возможность
|
||||
изменить период. При failed HTTP reread уже полученный Client Cached Snapshot
|
||||
остаётся на экране; это отличается от server-side failed hourly attempt.
|
||||
Повторная попытка перечитывает только HTTP-ответ. Без выбранного счёта запрос
|
||||
не выполняется. Смена сессии и подключения следует
|
||||
[общим правилам финансовых данных](../../architecture/cross-cutting/data-freshness.md).
|
||||
|
||||
Внешние границы объясняют интеграции [T-Bank](../../integrations/tbank.md)
|
||||
|
||||
@@ -1,46 +1,47 @@
|
||||
# Загрузка портфеля
|
||||
|
||||
Экран `/accounts/:accountId` читает последний полный snapshot из SQLite
|
||||
после проверки сессии, подключения и локального membership. Если список
|
||||
счетов ещё неизвестен, сервер сообщает о загрузке доступа без выдачи личных
|
||||
данных неизвестного ID. Известный недоступный счёт возвращает `404`.
|
||||
Экран `/accounts/:accountId` читает последний полный snapshot из SQLite после
|
||||
проверки сессии, подключения и локального membership. Если список счетов ещё
|
||||
неизвестен, сервер сообщает о загрузке доступа без выдачи личных данных
|
||||
неизвестного ID. Известный недоступный счёт возвращает `404`.
|
||||
|
||||
## Основной обмен
|
||||
|
||||
Обычный GET возвращает локальный envelope. Missing/stale зависимости
|
||||
запрашиваются в фоне; чтение не ждёт T-Bank. Для нового полного snapshot
|
||||
нужны оба финансовых ответа `GetPortfolio` и `GetPositions`. Суммы и позиции
|
||||
публикуются вместе; metadata дополняет представление независимо, с доступным
|
||||
UID/FIGI вместо имени до её загрузки.
|
||||
Обычный GET и retry возвращают read-only локальный `{ data, meta }` envelope:
|
||||
они не ждут и не вызывают T-Bank и не предлагают ручную синхронизацию. Часовой
|
||||
обход текущего подключения обновляет Portfolio независимо от экрана. Для нового
|
||||
полного snapshot ему нужны оба финансовых ответа `GetPortfolio` и
|
||||
`GetPositions`; суммы и позиции публикуются вместе. Metadata инструмента
|
||||
дополняет представление независимо, с доступным UID/FIGI вместо имени до её
|
||||
онлайн-загрузки.
|
||||
|
||||
Свежесть portfolio — 60 секунд. Истечение срока не удаляет snapshot и не
|
||||
создаёт таймер. «Обновить» на обзоре перечитывает зависимости текущего экрана:
|
||||
membership, portfolio, показанные операции, доход и будущие события.
|
||||
Секции могут быть готовы независимо. Подробнее —
|
||||
[свежесть](../../../architecture/cross-cutting/data-freshness.md).
|
||||
Открытый экран выполняет локальное перечитывание не чаще одного раза в
|
||||
30 минут; retry также повторяет только HTTP GET. `data: null` означает, что
|
||||
полного snapshot ещё нет, а не нулевой портфель. Пустой подтверждённый portfolio
|
||||
остаётся available complete result. Секции могут быть готовы независимо.
|
||||
Подробнее — [свежесть](../../../architecture/cross-cutting/data-freshness.md).
|
||||
|
||||
## Границы доступа
|
||||
|
||||
Публикация проверяет connection revision и attempt в той же транзакции.
|
||||
Замена или удаление подключения не допускает позднюю запись прежней работы.
|
||||
Frontend очищает недоступный personal view и отклоняет запоздалые ответы.
|
||||
В режиме [«Все счета»](../all-accounts.md#полнота-свежесть-и-доступ) состав
|
||||
accounts и snapshots читается согласованно, но их source times могут различаться.
|
||||
Публикация проверяет connection revision и attempt в той же транзакции. Замена
|
||||
или удаление подключения не допускает позднюю запись прежней работы. Frontend
|
||||
очищает недоступный personal view и отклоняет запоздалые ответы. В режиме
|
||||
[«Все счета»](../all-accounts.md#полнота-свежесть-и-доступ) состав accounts и
|
||||
snapshots читается согласованно, но их source times могут различаться.
|
||||
|
||||
## Ошибки и результат для пользователя
|
||||
|
||||
Нет подключения — `409 TBANK_NOT_CONNECTED`, известный отказ токена —
|
||||
`400 INVALID_TBANK_TOKEN`, недоступный счёт — `404`. Они не маскируются
|
||||
запасным snapshot. Transient source failure оставляет прежний полный портфель
|
||||
и его исходное время с безопасным предупреждением. При отсутствии snapshot
|
||||
показывается missing/failed, без нулевых итогов. `503` означает ошибку
|
||||
обслуживания HTTP-запроса, а не принятой фоновой работы.
|
||||
запасным snapshot. Временная ошибка часового обхода оставляет прежний полный
|
||||
portfolio и его исходное `lastSuccessfulAt`; `meta.lastAttempt` сообщает о
|
||||
failed или partial попытке отдельно. `Portfolio.isStale` сообщает возраст
|
||||
snapshot, а Client Cached Snapshot и ошибка браузерного HTTP-перечитывания
|
||||
имеют независимый смысл. При отсутствии полного snapshot `data: null` и
|
||||
metadata обозначает initial loading либо временную недоступность, без нулевых
|
||||
итогов. `503` означает ошибку обслуживания самого HTTP-запроса, а не
|
||||
завершившуюся фоновую работу.
|
||||
|
||||
Observer запрашивает статус известной работы, затем `sync=observe` читает
|
||||
изменившийся ресурс без запуска синхронизации. При уходе и terminal outcome
|
||||
наблюдение прекращается. Повторное открытие может запросить недостающее;
|
||||
после рестарта сохранённый snapshot доступен сразу.
|
||||
|
||||
Денежные правила находятся в [справочнике](../data-reference.md),
|
||||
проверка расхождения — в [диагностике](../how-to/investigate-discrepancy.md),
|
||||
RPC/лимиты — в [интеграции T-Bank](../../../integrations/tbank.md).
|
||||
Денежные правила находятся в [справочнике](../data-reference.md), проверка
|
||||
расхождения — в [диагностике](../how-to/investigate-discrepancy.md), RPC/лимиты
|
||||
— в [интеграции T-Bank](../../../integrations/tbank.md).
|
||||
|
||||
Reference in New Issue
Block a user