101 lines
9.2 KiB
Markdown
101 lines
9.2 KiB
Markdown
# Tasks
|
||
|
||
## 1. Данные попытки и вывод итога
|
||
|
||
- [x] 1.1 [backend] `settleHourly` выводит итог попытки из durable-строк шагов
|
||
в одной транзакции; `cause: 'INTERRUPTED'` капит итог до `partial`;
|
||
вызывающие не передают результат и список ошибок
|
||
- **Covers:** `hourly-investment-sync` — «Последний результат обхода доступен только для наблюдения»
|
||
- **Source:** Design — Decisions 1, 6; System Analysis — Data and State Semantics
|
||
- **Verification:** изолированный SQLite-тест: сбой после частичного обновления даёт `partial` с сохранённым успехом; сбой до первого шага даёт `failed`; ложный `succeeded` невозможен ни на одном error-пути
|
||
- **Depends on:** none
|
||
- [x] 1.2 [backend] id строк шагов персистятся в `progress` hourly-попытки
|
||
(`children` + `attempts`) в момент dispatch, до ожидания шага
|
||
- **Covers:** `hourly-investment-sync` — «Восстановление после сбоя сохранения не блокирует последующие обходы», «Устаревшая публикация не влияет на актуальную попытку»
|
||
- **Source:** Design — Decisions 2, 5
|
||
- **Verification:** SQLite-тест: после потери выполнения попытки множество шагов восстанавливается из `progress`, включая шаг, упавший в dispatch
|
||
- **Depends on:** 1.1
|
||
|
||
## 2. Ограниченное ожидание и восстановление
|
||
|
||
- [x] 2.1 [backend] ограничение ожидания на каждый шаг в `settledWorks`
|
||
(константа ~15 минут, per-id deadline); истёкший шаг учитывается проблемным
|
||
с причиной `DEADLINE`; начатые обращения к T-Bank не отменяются; часы в
|
||
тестах — jest fake timers без инъекции clock в production-код
|
||
- **Covers:** `hourly-investment-sync` — «Каждая попытка обхода достигает итога в ограниченное время»
|
||
- **Source:** Design — Decision 3; System Analysis — Error and Recovery Semantics
|
||
- **Verification:** SQLite-тест с зависшим шагом на fake timers: попытка терминальна в ограниченное время, наблюдение не ждёт бесконечно
|
||
- **Depends on:** 1.1
|
||
- [x] 2.2 [backend] in-memory `active`-реестр обходов + `recoverAbandoned`
|
||
перед reservation: running-попытка своего `processRunId` без активного walk
|
||
закрывается derived settle с `INTERRUPTED`; застрявшие legacy-строки
|
||
закрываются первым проходом
|
||
- **Covers:** `hourly-investment-sync` — «Восстановление после сбоя сохранения не блокирует последующие обходы» (Потерянное закрытие попытки)
|
||
- **Source:** Design — Decisions 4, 6; System Analysis — Error and Recovery Semantics
|
||
- **Verification:** SQLite-тест: подавленная ошибка закрытия при живом процессе — следующий проход закрывает попытку, следующая допустимая попытка стартует
|
||
- **Depends on:** 1.1, 1.2
|
||
- [x] 2.3 [backend] restart-ветка `reserveHourly` закрывает чужую running-попытку
|
||
derived settle с `INTERRUPTED` вместо голого `cancelled`; `due`-гейт и
|
||
защита от overlap прежние
|
||
- **Covers:** `hourly-investment-sync` — «Восстановление после сбоя сохранения не блокирует последующие обходы» (Перезапуск процесса)
|
||
- **Source:** Design — Decision 5
|
||
- **Verification:** SQLite-тест перезапуска процесса: брошенная попытка закрыта `partial`/`failed` с сохранёнными результатами шагов, новый обход не ранее следующего часового срока, перекрытия нет
|
||
- **Depends on:** 1.1, 1.2
|
||
|
||
## 3. Финализаторы шагов
|
||
|
||
- [x] 3.1 [backend] внешний catch финализаторов шагов (enrichment, operations
|
||
drain/step) записывает терминальный неуспешный результат своей строки шага
|
||
существующим путём записи ошибки перед возвратом или пробросом
|
||
- **Covers:** `hourly-investment-sync` — «Каждая попытка обхода достигает итога в ограниченное время» (шаг покидает running)
|
||
- **Source:** Design — Decision 7
|
||
- **Verification:** SQLite-тест с инъекцией ошибки финализатора: строка шага терминальна, попытка проходит terminal barrier
|
||
- **Depends on:** none
|
||
|
||
## 4. Поздняя публикация
|
||
|
||
- [x] 4.1 [backend] подтверждено fence-поведение публикации шага: результат до
|
||
фиксации итога попытки сохраняется и учитывается в итоге; после появления
|
||
преемника — отклоняется без изменения данных и итога актуальной попытки
|
||
- **Covers:** `hourly-investment-sync` — «Устаревшая публикация не влияет на актуальную попытку»
|
||
- **Source:** Design — Decisions 1–3; System Analysis — Error and Recovery Semantics
|
||
- **Verification:** SQLite-тесты поздней публикации: до фиксации итога — учтён; после successor — данные и итог актуальной попытки не изменились
|
||
- **Depends on:** 1.1, 1.2, 2.1
|
||
|
||
## 5. Системная верификация backend
|
||
|
||
- [x] 5.1 [backend] полный набор изолированных SQLite-тестов coordinator:
|
||
ветки `first`, `not-due`, `running`, `restart`, `partial`, итог после
|
||
terminal barrier; инъекции ошибок отдельно в дочерние шаги и родительский
|
||
coordinator; controlled stop/restart без бесконечного drain и без новых
|
||
reservations после остановки; scheduler stub `upcoming-events` не является
|
||
единственным доказательством
|
||
- **Covers:** `hourly-investment-sync` — все Requirements дельты
|
||
- **Source:** Design — Developer Verification Strategy; QA Analysis — Coverage Matrix, Risk-based Priorities
|
||
- **Verification:** полный `backend verify` зелёный на финальном diff; наборы auth/money/publication сохранены
|
||
- **Depends on:** 1.1, 1.2, 2.1, 2.2, 2.3, 3.1, 4.1
|
||
- [x] 5.2 [backend] backend-generated OpenAPI семантически совместим с
|
||
текущим контрактом: форма `meta` и словарь состояний не изменились, новые
|
||
значения только внутри открытого строкового поля диагностики
|
||
- **Covers:** `N/A` — защита контракта (изменений контракта нет)
|
||
- **Source:** Design — Contract Implementation; System Analysis — Contracts
|
||
- **Verification:** diff сгенерированного OpenAPI до/после изменения не содержит shape-изменений
|
||
- **Depends on:** 1.1, 1.2, 2.1, 2.2, 2.3, 3.1, 4.1
|
||
|
||
## 6. Canonical documentation
|
||
|
||
- [x] 6.1 [docs] обновить `data-freshness.md`: вывод итога из фактических
|
||
результатов шагов, ограниченное ожидание шага, закрытие брошенной попытки
|
||
без блокировки расписания — рядом со словарём `lastAttempt`
|
||
- **Covers:** `N/A` — docs promotion
|
||
- **Source:** docs-impact — Documentation Changes, строка 1
|
||
- **Verification:** страница не противоречит canonical spec `hourly-investment-sync` и фактическому поведению `meta`
|
||
- **Depends on:** 5.1
|
||
- [x] 6.2 [docs] обновить раздел «Состояние и ошибки» `tbank.md`: причины
|
||
жизненного цикла `INTERRUPTED`/`DEADLINE` — внутренняя диагностика, не
|
||
ошибки T-Bank; начатые обращения не отменяются
|
||
- **Covers:** `N/A` — docs promotion
|
||
- **Source:** docs-impact — Documentation Changes, строка 2
|
||
- **Verification:** раздел различает ошибки подключения/external-коды и внутренние причины жизненного цикла
|
||
- **Depends on:** 5.1
|