Быстрый приём: сохранение в catched, добавление в qBittorrent — шаг worker'а
Приём (Ingest) стал быстрым: синхронно только парс magnet, синтез контекста из полей ссылки, атомарный дедуп и запись загрузки в новое состояние `catched` — ответ клиенту сразу. Медленный вывод имени (LLM) и добавление в qBittorrent вынесены в асинхронный шаг машины состояний, который двигает worker. - store: состояние `catched` (нетерминальное, активная группа); атомарный переход PromoteCatched (catched → downloading + display_name) с гардом state='catched' (ре-валидация после сетевых вызовов вне блокировки) - ingest: убраны namer/qbt из пути приёма; пишем `catched`, отвечаем сразу - worker.processCatched: вне w.mu выводит имя и qbt.Add, под w.mu — короткий переход; сбой add оставляет catched (ретрай тиком); предохранитель catch_timeout → failed(qbit_add)+notify; catched исключён из проверок пропажи - config: worker.catch_timeout (дефолт 10m) - веб-UI: бейдж catched, активная группа, самозавершающийся htmx-поллинг карточки/страницы до перехода в downloading; Telegram-текст без сырого catched - OpenSpec: дельты ingest/download-tracking/web-ui влиты в спеки, change заархивирован Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -246,6 +246,33 @@ func TestIndexRenders(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Карточка catched несёт самозавершающийся htmx-поллинг (обновится без
|
||||
// перезагрузки при переходе в downloading) и человекочитаемый бейдж.
|
||||
func TestCatchedCardSelfPolls(t *testing.T) {
|
||||
reader := &fakeReader{get: &store.Download{
|
||||
ID: tid, SourceType: store.SourceMagnet, SourceRef: "magnet:?xt=urn:btih:abc",
|
||||
State: store.StateCatched,
|
||||
}}
|
||||
srv := newServer(t, httpapi.Deps{Ingestor: &fakeIngestor{}, Commander: &fakeCommander{}, Reader: reader})
|
||||
|
||||
resp, err := http.Get(srv.URL + "/fragments/downloads/" + tid + "/card")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("status = %d", resp.StatusCode)
|
||||
}
|
||||
s := string(body)
|
||||
if !strings.Contains(s, `hx-get="/fragments/downloads/`+tid+`/card"`) {
|
||||
t.Errorf("карточка catched без самополлинга: %s", s)
|
||||
}
|
||||
if !strings.Contains(s, "принято, добавляется") {
|
||||
t.Errorf("нет подписи бейджа catched: %s", s)
|
||||
}
|
||||
}
|
||||
|
||||
type ingestErr string
|
||||
|
||||
func (e ingestErr) Error() string { return string(e) }
|
||||
|
||||
Reference in New Issue
Block a user