hls: retire legacy basename-keyed HLS files on startup
Adds `video::legacy_migration::retire_legacy_hls_output`, called once from `main` right after the diesel migrations run and before the actor pipeline starts. Walks `$VIDEO_PATH` at depth 1, deletes every `.m3u8` / `.m3u8.tmp` / `.m3u8.unsupported` / `.ts` file at root, and logs a single info line with per-class counts. Skips directories (the new layout's `<shard>/<hash>/` lives there) and unknown extensions, so an operator's stashed README or `.tmp` from a different tool is safe. Why this needs its own one-shot pass rather than letting the rewritten `cleanup_orphaned_playlists` handle it: the cleanup walk deliberately only looks at `<shard>/<hash>/` dirs (so it can't accidentally `rm` operator-stashed content), so without this migration the legacy files would sit at root forever, never served, never refreshed. Operator complaint count from the previous IMG_NNNN.MOV collision: ~10 duplicate-basename hits on one library alone; total .m3u8 count was 699 vs a much larger video count — i.e. the loser of every collision was a permanent orphan. This pass collects all of them, then the running watcher writes hash-keyed playlists going forward. Idempotent — a second boot finds nothing and reports zero deletions, so the call site can stay in `main` across releases until the module is removed in a later cleanup commit. Tests cover the happy path (legacy artifacts gone, hash dir untouched, unrelated files left alone), idempotency, and the missing-directory case. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+10
@@ -72,6 +72,16 @@ fn main() -> std::io::Result<()> {
|
||||
|
||||
run_migrations(&mut connect()).expect("Failed to run migrations");
|
||||
|
||||
// One-shot retirement of the pre-content-hash HLS layout. Idempotent
|
||||
// — a second boot finds nothing and reports zero deletions, so it's
|
||||
// safe to leave wired in until the module is removed in a later
|
||||
// release. Runs before the actor pipeline starts so we never race a
|
||||
// PlaylistGenerator write against this rm.
|
||||
{
|
||||
let video_path = env::var("VIDEO_PATH").expect("VIDEO_PATH was not set in the env");
|
||||
video::legacy_migration::retire_legacy_hls_output(std::path::Path::new(&video_path));
|
||||
}
|
||||
|
||||
let system = actix::System::new();
|
||||
system.block_on(async {
|
||||
// Just use basic logger when running a non-release build
|
||||
|
||||
Reference in New Issue
Block a user