spec: add harden-hourly-sync-lifecycle change (WealthLedger/backend#56)
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
# Proposal
|
||||
|
||||
## Why
|
||||
|
||||
Почасовая синхронизация T-Bank может завершиться в неконсистентном состоянии
|
||||
после ошибки сохранения: незавершённая попытка записывается как полный успех,
|
||||
ошибка финализации либо подавленная ошибка закрытия оставляет попытку в
|
||||
состоянии выполнения навсегда, а локальная reservation не позволяет запустить
|
||||
следующий обход в том же процессе. Пользователь видит ложный успех и перестаёт
|
||||
получать обновления до перезапуска backend, а неудавшееся ожидание дочерних
|
||||
шагов может ждать без ограничения. Механизм подтверждён статически (BE-002,
|
||||
BE-015, RISK-001, RISK-002, TQ-003); частота проявления в production пока не
|
||||
установлена.
|
||||
|
||||
## What Changes
|
||||
|
||||
- Итог попытки определяется фактическим результатом каждого обязательного шага:
|
||||
невыполненный шаг даёт частичный успех либо неуспех, но не полный успех, а
|
||||
уже полученные успехи отдельных счетов и разделов сохраняются.
|
||||
- Прерванная попытка (ошибка, сбой сохранения, остановка процесса, истечение
|
||||
ожидания) обозначается частичным успехом либо неуспехом и не получает нового
|
||||
публичного состояния; причина прерывания фиксируется существующим
|
||||
диагностическим полём.
|
||||
- Попытка достигает итога в ограниченное время: ожидание дочернего шага
|
||||
ограничено, а зависшая попытка не остаётся в выполнении бесконечно.
|
||||
- Состояние в SQLite восстанавливается после сбоя сохранения: брошенная попытка
|
||||
закрывается диагностируемым итогом, ожидание завершается, следующая
|
||||
допустимая попытка может стартовать без перезапуска процесса.
|
||||
- Восстановление не создаёт перекрытия обходов и не принимает устаревшие
|
||||
результаты: поздняя публикация относительно актуального преемника
|
||||
отклоняется.
|
||||
|
||||
## Scope
|
||||
|
||||
### In Scope
|
||||
|
||||
- Итоговый статус попытки часового обхода и обработка ошибок в дочерних
|
||||
финализаторах.
|
||||
- Ограниченное ожидание дочерних шагов и восстановление после ошибок
|
||||
завершения шага, публикации результата и закрытия попытки.
|
||||
- Защита от перекрытия обходов и от поздней публикации устаревших данных при
|
||||
восстановлении.
|
||||
- Контролируемая остановка и перезапуск процесса и их влияние на незавершённую
|
||||
попытку, подтверждённые тестами.
|
||||
- Наблюдаемый результат попытки: время начала, состояние, безопасный перечень
|
||||
проблемных счетов и разделов.
|
||||
|
||||
### Out of Scope / Non-Goals
|
||||
|
||||
- Распределённая очередь, lease, поддержка нескольких реплик и изменение
|
||||
топологии deployment.
|
||||
- Удаление данных.
|
||||
- Ослабление существующих ограничений CAS для попытки, ревизии подключения и
|
||||
источника данных.
|
||||
- Новый публичный статус попытки и изменения HTTP contract.
|
||||
- Новый параллельный scheduler или замена владельцев строк синхронизации.
|
||||
- Проверка часовой cadence и cleanup workflow — независимые задачи.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- Нет.
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `hourly-investment-sync`: итог попытки из фактических результатов шагов,
|
||||
ограниченное ожидание шага, диагностируемое закрытие брошенной попытки,
|
||||
отсутствие перекрытий и устаревшей публикации.
|
||||
|
||||
## Impact
|
||||
|
||||
- **Пользователь**: достоверный статус последнего обхода вместо ложного успеха
|
||||
и бесконечного «выполняется» после сбоя сохранения; обновления продолжаются
|
||||
без перезапуска процесса.
|
||||
- **Backend**: координатор часового обхода, дочерние финализаторы обновления
|
||||
данных и reservation попытки в SQLite.
|
||||
- **Frontend**: не затрагивается — наблюдаемый словарь состояний и форма
|
||||
ответов не меняются.
|
||||
- **Внешняя система T-Bank**: contract не меняется; начатые запросы к T-Bank
|
||||
могут завершаться поздно и должны корректно отклоняться как устаревшие.
|
||||
- **Процессы**: диагностика причин прерывания попыток и восстановление после
|
||||
ошибок сохранения.
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- Попытка с невыполненным обязательным шагом никогда не наблюдается как полный
|
||||
успех; частичные успехи счетов и разделов остаются видимыми.
|
||||
- После однократной ошибки завершения шага, публикации результата либо закрытия
|
||||
попытки и последующего восстановления ожидание завершается, а следующая
|
||||
допустимая попытка стартует.
|
||||
- Устаревшая попытка наблюдается относительно актуального преемника; поздняя
|
||||
публикация старого процесса отклоняется и не меняет данные.
|
||||
- Координатор различает состояния `first`, `not-due`, `running`, `restart` и
|
||||
`partial`; итог проверяется после terminal barrier.
|
||||
- Сценарий остановки и перезапуска доказан тестами: нет бесконечного ожидания,
|
||||
после остановки новые попытки не создаются.
|
||||
- Сохранены существующие наборы проверок auth/money/publication, полный
|
||||
`backend verify` на финальном изменении зелёный.
|
||||
|
||||
## Assumptions / Dependencies
|
||||
|
||||
- Топология остаётся одно-процессной; межпроцессный lease и мультреплики не
|
||||
требуются.
|
||||
- Истечение ожидания не отменяет уже начатый запрос к T-Bank; защита
|
||||
опирается на существующие ограничения CAS и правило срока следующего обхода.
|
||||
- Причина прерывания фиксируется существующим диагностическим полём, поэтому
|
||||
HTTP contract и публичный словарь состояний не меняются; упомянутое в задаче
|
||||
состояние `interrupted` реализуется как частичный успех либо неуспех.
|
||||
- Graceful drain добавляется только если тест контролируемой остановки докажет
|
||||
такую необходимость.
|
||||
- Правило устаревшей публикации относится к итогу попытки и данным её шагов;
|
||||
существующие требования `tbank-data-sync` уже запрещают выдавать неполный или
|
||||
продолжающийся результат за полный, поэтому их изменение не планируется.
|
||||
Reference in New Issue
Block a user