Два связанных бага семантики таймаутов зависания и ручного retry. MAJOR-1: Retry живого торрента не сбрасывал базис отсчёта таймаута — задача мгновенно снова падала в stuck на ближайшем тике. Вводим колонку download.retried_at (миграция 0010): ручной retry фиксирует момент и приподнимает пол обоих таймаутов (max(базис, retried_at)). Хранится в БД, а не в памяти, чтобы сброс пережил тик поллинга и рестарт. MAJOR-2: stuck_after мерил ВОЗРАСТ торрента (от added_on), а не ПРОСТОЙ — долго качавшийся торрент, на миг зашедший в stalledDL, ложно уходил в stuck со «stalled for 5h». Теперь stuck_after мерит простой от qBit last_activity (новое поле qbt.Torrent из того же ответа /torrents/info); magnet_timeout по-прежнему мерит возраст (семантически верно). checkTimeouts разбит на torrentAge/stallDuration/addedBasis/retriedFloor. NIT-10: фолбэк базиса возраста added_on→created_at сохранён и покрыт. NIT-12: retry перестаёт перецепляться к сломанному живому торренту (error/missingFiles) — повторно отдаёт источник (перецепка к нему бессмысленна: reconcile тут же вернул бы в failed). Спека: дельта state-reconciliation (MODIFIED «Восстановление зависшей загрузки» и «Ручной повтор»), правка docs/specs/workflow.md (устранено противоречие «возраст vs простой»), ER-схема database.md. Тесты: TestRetryResetsTimeoutBasis (следующий тик после retry — прячется в TestRetryReattachesNoReadd), TestStallMeasuredFromLastActivity, TestSetRetriedAtOverwrites. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
12 lines
850 B
SQL
12 lines
850 B
SQL
-- +goose Up
|
|
-- Время последнего ручного retry задачи (RFC 3339 UTC, суффикс Z). Приподнимает
|
|
-- базис отсчёта таймаутов (magnet_timeout/stuck_after): после retry отсчёт идёт
|
|
-- от max(базис_добавления или last_activity, retried_at), чтобы возврат в
|
|
-- downloading не ронял задачу снова на ближайшем тике (см. state-reconciliation
|
|
-- «Ручной повтор зависшей/упавшей загрузки»). Хранится в БД, а не в памяти,
|
|
-- чтобы сброс базиса пережил интервал поллинга и рестарт процесса.
|
|
ALTER TABLE download ADD COLUMN retried_at TEXT;
|
|
|
|
-- +goose Down
|
|
ALTER TABLE download DROP COLUMN retried_at;
|