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.
39 lines
3.0 KiB
Markdown
39 lines
3.0 KiB
Markdown
# TASK 55 — Disk hygiene: log rotation + low-disk guard (queued 2026-10-09)
|
||
|
||
> Catalog: [`TASKS.md`](../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.
|