import { stat } from "node:fs/promises"; import { measureTree } from "yt-dlp-transcript-common/controller/relocateDir"; // THE SAVED-VIDEO STORE'S SIZE, MEASURED AT MOST ONCE EVERY 60 SECONDS. // // `measureTree` is a recursive walk. On /storage it is the one thing on the // page that touches the disk per render rather than reading a report, and it // is there because the store holds ONE container per pinned or kept-latest // video — a few dozen files — not one per video. That is what makes a walk // affordable at all. // // But "affordable" was doing a lot of work for a `force-dynamic` page the // global AutoRefresh re-renders on a timer, and the store is the one directory // in the corpus that can grow without anybody deciding it should: every pin, // every `keepSourceVideo`, every umtool full-source fetch lands a container in // it. A page that walks a growing directory on every refresh gets slower in // exactly the situation the operator opened it to understand. // // KEYED BY THE DIRECTORY'S OWN MTIME, and capped at sixty seconds. The TTL // alone was wrong and an e2e caught it within the hour: a spec seeded a // container into the store and the page went on reporting "0 B in 0 file(s)" // from a walk taken before the seed. A cache that makes a page lie about a // number the operator just changed is worse than the walk it saves. // // Adding or removing an entry in a directory bumps THAT directory's mtime, so // the common cases — the first container landing, a prune, a move that replaces // the store with a symlink, an e2e reset — all invalidate on the next render. // A write deeper in the tree (a container added inside an existing // `/