spec: add harden-hourly-sync-lifecycle change (WealthLedger/backend#56)
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
# System Analysis
|
||||
|
||||
## Requirement Coverage
|
||||
|
||||
| Requirement / Scenario | Flow | Contract / Semantics |
|
||||
| --- | --- | --- |
|
||||
| Последний результат обхода… — Сбой после частичного обновления | `hourly-attempt-terminal-barrier.mmd` | Outcome derivation, terminal barrier |
|
||||
| Последний результат обхода… — Сбой до первого обновления | `hourly-attempt-terminal-barrier.mmd` | Outcome derivation |
|
||||
| Последний результат обхода… — Частичный успех | `hourly-attempt-terminal-barrier.mmd` | Step results preserved |
|
||||
| Каждая попытка обхода достигает итога в ограниченное время — Шаг не завершается | `hourly-bounded-wait.mmd` | Bounded wait per required step |
|
||||
| Каждая попытка обхода достигает итога в ограниченное время — Наблюдение не ждёт без ограничения | `hourly-bounded-wait.mmd` | Bounded terminal outcome |
|
||||
| Восстановление после сбоя сохранения… — Потерянное закрытие попытки | `hourly-recovery.mmd` | Recovery of lost settle |
|
||||
| Восстановление после сбоя сохранения… — Перезапуск процесса | `hourly-recovery.mmd` | Recovery of abandoned attempt |
|
||||
| Устаревшая публикация… — Поздняя публикация после появления преемника | `hourly-recovery.mmd` | Successor fencing |
|
||||
| Устаревшая публикация… — Поздняя публикация до фиксации итога | `hourly-bounded-wait.mmd` | Late publication counts before outcome is recorded |
|
||||
|
||||
## Systems and Responsibilities
|
||||
|
||||
- **Hourly walk coordinator** (backend): резервирует попытку часового обхода для
|
||||
текущего подключения, запускает обязательные шаги, ждёт их терминального
|
||||
результата с ограничением, выводит итог попытки и закрывает её.
|
||||
- **Durable attempt status** (SQLite): единственная durable-запись попытки
|
||||
(состояние, диагностическая причина, результаты шагов) и источник итога для
|
||||
наблюдения и восстановления.
|
||||
- **Child step owners**: шаги membership, Portfolio, операций и будущих событий
|
||||
публикуют свой полный результат в durable-хранилище и обозначают свой
|
||||
терминальный результат; финализатор шага обязан фиксировать результат даже
|
||||
при ошибке.
|
||||
- **T-Bank и публичные источники**: внешние данные; начатые обращения не
|
||||
отменяются по внутреннему ограничению ожидания.
|
||||
- **Resource GET observer**: читает сохранённые данные и `meta` с состоянием
|
||||
последней попытки; наблюдение не запускает обход.
|
||||
|
||||
## Interaction Flows
|
||||
|
||||
- `sequences/hourly-attempt-terminal-barrier.mmd` — попытка, шаги, terminal
|
||||
barrier и вывод итога из фактических результатов шагов.
|
||||
- `sequences/hourly-bounded-wait.mmd` — ограничение ожидания шага, закрытие
|
||||
попытки по его истечении и учёт позднего результата до появления преемника.
|
||||
- `sequences/hourly-recovery.mmd` — восстановление после сбоя сохранения и
|
||||
после перезапуска процесса, отклонение устаревшей публикации.
|
||||
|
||||
## Contracts
|
||||
|
||||
- Новых и изменённых межсистемных HTTP/event contracts нет. Публичный словарь
|
||||
состояний последней попытки (`выполнение`, `полный успех`, `частичный успех`,
|
||||
`неуспех`) и форма `{ data, meta }` не меняются.
|
||||
- Машинно-читаемый target contract в `system-analysis/contracts/` не создаётся:
|
||||
изменения ограничены уточнением значений внутри существующих полей.
|
||||
- Диагностическое поле причины остаётся открытым строковым полем; значения
|
||||
причин прерывания (`INTERRUPTED` — ошибка, сбой сохранения, остановка
|
||||
процесса; `DEADLINE` — истечение ограничения ожидания шага) дополняют
|
||||
существующие коды ошибок шагов и не требуют изменения формы ответа.
|
||||
- Compatibility check до закрытия change: backend-generated OpenAPI остаётся
|
||||
семантически совместимым с текущим контрактом (ожидаются только дополнительные
|
||||
значения открытого строкового поля диагностики).
|
||||
|
||||
## Data and State Semantics
|
||||
|
||||
- **Попытка**: `running` → терминальный итог (`succeeded` | `partial` | `failed`).
|
||||
Попытка, не завершившая обязательный шаг, не может получить `succeeded`.
|
||||
- **Terminal barrier**: итог попытки выводится только после того, как каждый
|
||||
обязательный шаг достиг терминального результата либо учтён как истёкший по
|
||||
ограничению ожидания. Итог не вычисляется по неполному списку шагов.
|
||||
- **Вывод итога**: `succeeded` — только когда все обязательные шаги успешны и
|
||||
координатор сам зафиксировал закрытие попытки; `partial` — успешны некоторые
|
||||
шаги; `failed` — не успешен ни один. Успешные результаты шагов сохраняются
|
||||
независимо от итога.
|
||||
- **Причина прерывания**: попытка, закрытая до нормального завершения всех
|
||||
шагов, сохраняет причину прерывания в диагностическом поле и не превышает
|
||||
`partial`.
|
||||
- **Internal coordinator decisions** `first`, `not-due`, `running`, `restart`,
|
||||
`partial`: внутренние метки решения о запуске и проверки итога после terminal
|
||||
barrier; в HTTP contract не входят и публично не наблюдаемы.
|
||||
- **Шаги**: каждый шаг владеет своей durable-строкой результата; строка шага
|
||||
устаревшей попытки помечается устаревшей относительно преемника.
|
||||
|
||||
## Error and Recovery Semantics
|
||||
|
||||
- **Сбой шага** (внешняя ошибка T-Bank): шаг фиксирует терминальный неуспех со
|
||||
своим кодом ошибки; остальные шаги продолжаются; итог — `partial` или `failed`.
|
||||
- **Сбой сохранения** (завершение шага, публикация результата, закрытие
|
||||
попытки): ошибка не подавляется молча в durable-состоянии; попытка, оставшаяся
|
||||
`running`, закрывается восстановлением по фактическим результатам шагов.
|
||||
- **Остановка процесса**: начатая попытка остаётся `running` в SQLite;
|
||||
следующий запуск процесса закрывает её как прерванную (`partial` или `failed`
|
||||
с сохранёнными результатами шагов) и не создаёт перекрывающийся обход.
|
||||
- **Ограничение ожидания**: истечение ограничивает только ожидание шага; уже
|
||||
начатое обращение к T-Bank не отменяется. Его поздний результат сохраняется и
|
||||
учитывается при выводе итога своей попытки, если итог ещё не зафиксирован, и
|
||||
отклоняется как устаревший после появления преемника.
|
||||
- **Повтор**: неуспешная попытка не повторяется ранее следующего часового срока,
|
||||
отсчитанного от начала этой попытки; восстановление не сокращает и не
|
||||
продлевает этот срок.
|
||||
- **Overlapping**: следующая попытка не резервируется, пока предыдущая не
|
||||
терминальна; восстановление обязано сначала закрыть предыдущую.
|
||||
|
||||
## Observability Semantics
|
||||
|
||||
- Наблюдаемый итог попытки и безопасный перечень проблемных счетов/разделов —
|
||||
существующее обязательство; значения итога не расширяются.
|
||||
- Семантические коды причин: `INTERRUPTED` — попытка прервана до нормального
|
||||
завершения (ошибка, сбой сохранения, остановка процесса); `DEADLINE` — шаг не
|
||||
завершился в ограничение ожидания. Коды сохраняются в диагностическом поле
|
||||
попытки и/или шага и дополняют коды ошибок шагов без изменения формы `meta`.
|
||||
- SDK/exporter/logger — вне границ этого изменения; используется существующий
|
||||
структурный лог backend.
|
||||
|
||||
## Security and NFR at System Boundaries
|
||||
|
||||
- Граница наблюдения попытки остаётся границей текущего подключения: результат
|
||||
прежней границы не раскрывается (существующее обязательство).
|
||||
- Ограниченное время достижения итога попытки — наблюдаемое обязательство
|
||||
надёжности: ожидание шага и ожидание наблюдателя ограничены.
|
||||
- Новых trust boundaries, authn/authz требований нет.
|
||||
|
||||
## Compatibility / Migration
|
||||
|
||||
- Схема данных и HTTP contract не меняются; миграция не требуется.
|
||||
- Уже застрявшие строки попыток в состоянии выполнения закрываются первым
|
||||
проходом восстановления по правилам этого изменения: итог из фактических
|
||||
результатов шагов, причина прерывания, без полного успеха. Это ожидаемое
|
||||
разовое приведение legacy-состояния к диагностируемому виду.
|
||||
- Совместимость с одно-процессной топологией сохраняется; межпроцессный lease
|
||||
не требуется.
|
||||
|
||||
## Durable Documentation Candidates
|
||||
|
||||
- `docs/integrations/tbank.md` (раздел «Состояние и ошибки»): итог часовой
|
||||
попытки, причины прерывания и правило ограниченного ожидания как часть
|
||||
наблюдаемого состояния интеграции.
|
||||
- `docs/architecture/containers.md` (раздел «Сохранение и восстановление
|
||||
данных»): восстановление попытки после сбоя сохранения и после перезапуска
|
||||
процесса как durable-свойство системы.
|
||||
- Итоговое решение о переносе принимает `docs-impact`.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Нет блокирующих вопросов. Частота проявления механизма в production остаётся
|
||||
не установленной и не влияет на contract.
|
||||
Reference in New Issue
Block a user