Skip to content

feat(engine): auto-free disk space with retention + hard cap#2

Merged
jodacame merged 1 commit into
mainfrom
feat/disk-retention
Jul 1, 2026
Merged

feat(engine): auto-free disk space with retention + hard cap#2
jodacame merged 1 commit into
mainfrom
feat/disk-retention

Conversation

@jodacame

@jodacame jodacame commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Qué hace

En modo disco, el espacio ya no se llena: lo que deja de ser necesario se borra, y la carpeta de descargas queda acotada por un tope configurable (el análogo en disco del ring buffer de RAM).

Política (internal/engine/janitor.go)

  • retire() — torrent que ya no se necesita:
    • Privado → borrado inmediato (su ratio/tiempo del tracker ya fue su ventana).
    • Público → se saca de activos pero se conserva en disco con PendingDeleteAt = ahora + gracia; si el espectador vuelve, reanuda al instante desde los archivos retenidos.
  • Loop janitor (cada 30 s): borra lo pendiente cuando pasa la ventana; si se supera Disk.MaxGB, desaloja lo más viejo primero (el tope duro manda sobre la gracia).
  • Nunca toca lo que se está viendo (readers>0) ni lo que seedea hacia un objetivo vivo.

Disparadores conectados

Evento Antes Ahora
Seed cumple ratio/tiempo Drop (dejaba archivo) retire (deleteAfterSeed)
Fin de reproducción / idle en disco Drop (dejaba archivo) retire (deleteAfterPlayback)
Re-añadir un torrent pendiente rescate: limpia el flag y reanuda

Guardas de seguridad (borrado automático)

  • Rechaza nombre vacío (evita borrar toda la carpeta) y path traversal por nombre malicioso (safeDataPath).
  • Borra solo records en modo disco.
  • El borrado manual "con archivos" pasa por la misma guarda.

Ajustes (en Settings, editables en la UI — no env)

disk.maxGB, disk.graceMinutes, disk.deleteAfterSeed, disk.deleteAfterPlayback. TorrentRecord gana PendingDeleteAt.

Verificación

  • Tests nuevos: guardas de safeDataPath (rechaza ../../etc y vacío), dirSize, orden de evictKey, deleteRecordFiles. Backend go build+vet+test en verde; frontend tsc+vite build OK.
  • En vivo (contenedor modo disco): boot OK, GET/PUT /api/settings exponen y persisten el bloque disk, maxGB=-3 normaliza a 0, sin panics, janitor corriendo.

Nota de garantía

Con esto: se conserva solo lo activo o con seed vivo; lo demás se limpia (con colchón de gracia para reanudar sin re-descargar); y el disco nunca supera disk.maxGB.

🤖 Generated with Claude Code

Disk mode never fills up now: content that is no longer needed is removed, and
the download folder is bounded by a configurable cap (the disk analogue of the
RAM ring-buffer).

Policy (internal/engine/janitor.go):
- retire(): a torrent no longer needed. Private torrents are deleted immediately
  (their tracker ratio/time already served as the retention window); public
  torrents are dropped from the active set but kept on disk and marked
  PendingDeleteAt = now + grace, so a returning viewer resumes instantly.
- janitor loop: deletes pending content once its grace window elapses; if the
  dir exceeds Disk.MaxGB, evicts the oldest inactive content first (the hard cap
  overrides the grace window).
- Never touches content being watched (readers>0) or seeding toward a live target.

Triggers wired:
- seed ratio/time target met -> retire (was: drop, leaving files) [deleteAfterSeed]
- end of playback / idle timeout in disk mode -> retire [deleteAfterPlayback]
- re-adding a pending torrent clears the flag (rescue from retained files).

Safety guards for automatic deletion: reject empty names and path traversal via
crafted torrent names (safeDataPath), delete only disk-mode records, and route
manual delete-with-files through the same guard.

Settings (config.Disk, editable in the UI, not env): maxGB, graceMinutes,
deleteAfterSeed, deleteAfterPlayback. TorrentRecord gains PendingDeleteAt.

Tests: safeDataPath guards, dirSize, evictKey ordering, deleteRecordFiles.
Docs: README "Disk cleanup" section.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012bj3G2zzqEaALFa8ufbkDJ
@jodacame
jodacame merged commit 0aa70cf into main Jul 1, 2026
2 checks passed
@jodacame
jodacame deleted the feat/disk-retention branch July 1, 2026 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant