layout: непомещающееся целевое имя уводит задачу в review вместо failed

- предел длины компонента (255 байт) проверяется в BuildLinks до первой
  операции с ФС: ни каталога, ни ссылки при отказе не создаётся
- причина пустого предпросмотра считается на показе (ReviewData.PreviewError)
  и печатается в панели действий и в карточке Telegram: у задачи без
  записанной причины взять её больше неоткуда
This commit is contained in:
av
2026-08-10 12:16:44 +03:00
parent 1710e5a9d5
commit b9f0929d0c
31 changed files with 1511 additions and 17 deletions
+22
View File
@@ -1098,3 +1098,25 @@ func TestRerecognize(t *testing.T) {
t.Errorf("rerecognized = %v, want [%s]", rv.rerecognized, tid)
}
}
func TestAPICommandNameTooLong(t *testing.T) {
// Непомещающееся целевое имя (layout.ErrNameTooLong) → 409 (штатно ушло в
// review), не 500: это конфликт, требующий разбора, а не сбой сервера.
// Наружу — нейтральное сообщение, сырой текст ошибки остаётся в логах.
cmd := &fakeCommander{err: fmt.Errorf("apply: %w", layout.ErrNameTooLong)}
srv := newServer(t, httpapi.Deps{Ingestor: &fakeIngestor{}, Commander: cmd, Reader: &fakeReader{}})
resp, err := http.Post(srv.URL+"/api/downloads/"+tid+"/cancel", "", nil)
if err != nil {
t.Fatal(err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusConflict {
t.Fatalf("status = %d, want 409", resp.StatusCode)
}
var got map[string]any
_ = json.NewDecoder(resp.Body).Decode(&got)
if msg, _ := got["error"].(string); !strings.Contains(msg, "слишком длинное") {
t.Errorf("error = %q, want содержащее «слишком длинное»", msg)
}
}