Files
LlamaCasty/TASKS/task-55-disk-hygiene.md
T
gramps 1a6a549e17 feat(55): stop leaving disk debts — temp clips and a low-disk guard
595 green, 0 warnings. Completes TASK 55 (slice 1, log rotation, shipped 2026-10-22).

- **`AlertClipCleanup`**: the default alert clip is materialised into `%TEMP%` for ffmpeg to read, and
  nothing ever deleted it — one orphan per profile that ever played an alert. Now: delete this session's
  file in `Shutdown`, and sweep `ytLive-alert-*.mp4` at startup for anything a crash left behind. Only
  the prefix we own is touched; a directory is never deleted.
- **`DiskSpaceGuard`**: a recording that dies of a full disk is a trust breach, so the numbers are a
  pure policy — refuse to start under **1 GB** (toast; the stream still starts, recording does not),
  warn under **5 GB** at start ("about eighty minutes" at 8 Mbps ≈ 3.6 GB/h), and one mid-show warning
  under **2 GB** — the last useful moment before the encoder fails for a reason it won't explain.
  Unreadable drives (a USB stick that just left) return null and never block a running recording.

Tests are policy-level on purpose: filling a real drive is not a test. `DiskHygieneTests` proves the
sweep only removes our own files and that the thresholds behave at both ends.
2026-11-10 11:55:42 -08:00

3.0 KiB
Raw Blame History

TASK 55 — Disk hygiene: log rotation + low-disk guard (queued 2026-10-09)

Catalog: TASKS.md — status and requirements live here.

Why (creator ask, 2026-10-09): "we need some sort of log-rotation so that we don't inadvertently fill up a user's drive." A free app that quietly eats disk space is a support ticket and a trust breach.

What's known (from the 2026-10-09 privacy-policy code research — re-verify before building):

  • Helpers/AppLog.cs appends to %APPDATA%\ytLlive\startup.log, a timestamped line per entry, with no size cap or rotation found (not specifically searched — confirm first).
  • Services/Encoder/FfmpegEncoder.cs (~:371) logs every non-progress ffmpeg stderr line (≤400 chars each) — the main growth source over long streams.
  • Default alert clip is written to %TEMP%\ytLive-alert-<id>.mp4 (ViewModels/MainViewModel.Chat.cs ~:106) — confirm whether it's ever deleted.
  • Recordings (.mp4, default Downloads) are user-directed, but nothing checks free space.

Slices (one integration test each, in order):

  1. ✅ Size-capped log rotation — when startup.log passes a cap (~5 MB), roll it to startup.1.log (keep 1–2 old files), start fresh. Test: write past the cap, assert the roll and the bounded total. Standard pattern (NLog/Serilog fileSizeLimitBytes + retainedFileCountLimit) — cite in the commit.
    • SHIPPED 2026-10-22. Helpers/LogRotation.cs (new) holds the policy as a pure function over a path — RollIfNeeded(logPath, maxBytes, retainedFiles) shifts name.1.log → name.2.log → … and the live file → name.1.log, so the file set is bounded, not just the live file. AppLog calls it before each append (cap 5 MB, 1 rolled copy) and keeps its 156-call-site surface unchanged; the test seams are two internal properties (PathOverride, MaxBytes) — the app project already has InternalsVisibleTo("ytLive.Tests"). Guard: ytLive.Tests/AppLogRotationTests.cs (the ONE test: the log rolls at the cap, the live file starts fresh, and the directory still holds exactly startup.log + startup.1.log after a SECOND roll — the growth is bounded).
  2. ✅ Temp alert clip cleanup — Services/AlertClipCleanup deletes the session's clip on close and sweeps ytLive-alert-*.mp4 at startup (never anything else); shipped 2026-11-10 — delete the %TEMP% alert clip on app close (and sweep stale ones at startup). Test: create, close, assert gone.
  3. ✅ Low-disk guard for recordings — Services/DiskSpaceGuard: refuse to start under 1 GB (toast, recording not started, stream continues), warn under 5 GB at start, one mid-show warning under 2 GB; shipped 2026-11-10 — check free space on the record folder's drive before Record starts, and warn (toast) when it runs low mid-recording. Thresholds chosen for 8 Mbps ≈ 3.6 GB/h; revisit if tiers change.

Design decisions: keep AppLog's call surface unchanged — rotation lives inside it.