Files
specs/openspec/changes/harden-hourly-sync-lifecycle/tasks.md
T
ksv741 14174a7bb3
Conventional commits / commits (pull_request) Successful in 12s
Specs security / security (pull_request) Successful in 7s
Specs verify / verify (pull_request) Successful in 10s
spec: add harden-hourly-sync-lifecycle change (WealthLedger/backend#56)
2026-10-12 20:28:58 +03:00

9.2 KiB
Raw Blame History

Tasks

1. Данные попытки и вывод итога

  • 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
  • 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. Ограниченное ожидание и восстановление

  • 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
  • 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
  • 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. Финализаторы шагов

  • 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. Поздняя публикация

  • 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

  • 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
  • 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

  • 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
  • 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