feat(downloads): pre-flight free-disk guard before each download (hueco medio)
CheckDiskSpace (internal/engine/diskspace.go) refuses a download before writing when its expected size wouldn't leave a configurable reserve free, so a download never fills the filesystem to 0 mid-write (which corrupts the partial file). Wired into all three downloaders ahead of any write — torrent (DataDir), debrid (outputDir, resume-aware), usenet (outputDir, fresh only). Reserve from downloads.min_free_disk_mb (default 2048 MiB) via SetMinFreeBytes. The manager treats an InsufficientDiskError as terminal — no source fallback, since another source would fill the same disk — and surfaces the clear message. Best-effort: unknown size or a stat failure doesn't block (ENOSPC stays the backstop). Also hardens formatBytes against an exabyte-scale out-of-bounds panic.
This commit is contained in:
parent
2be92516c6
commit
1cad73b9a7
9 changed files with 196 additions and 4 deletions
|
|
@ -344,6 +344,12 @@ func (m *Manager) processTask(ctx context.Context, task *Task) {
|
|||
close(progressCh)
|
||||
|
||||
if err != nil {
|
||||
// A full disk is terminal — another source would fill the same disk, so
|
||||
// skip the fallback and surface the clear message immediately.
|
||||
if IsInsufficientDisk(err) {
|
||||
m.fail(ctx, task, err.Error())
|
||||
return
|
||||
}
|
||||
// Try fallback
|
||||
if tryFallback(task, m.downloaders) {
|
||||
log.Printf("[%s] %s failed, trying fallback: %v", agent.ShortID(task.ID), method, err)
|
||||
|
|
@ -386,6 +392,8 @@ func (m *Manager) processTaskRetry(ctx context.Context, task *Task) {
|
|||
close(progressCh)
|
||||
|
||||
if err != nil {
|
||||
// No further fallback here — same disk, same outcome — so an
|
||||
// InsufficientDiskError on the fallback surfaces its message directly.
|
||||
m.fail(ctx, task, err.Error())
|
||||
return
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue