# 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` уже запрещают выдавать неполный или продолжающийся результат за полный, поэтому их изменение не планируется.