Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit b8fe7c2c2baf6fe48619f88bc92b83ef5bd745e2
parent 470b78d696e83fe5b9a3eff907f5fdcf0d0b4b94
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Tue, 22 Sep 2026 16:04:23 -0400

editor: Sync all skips a channel whose media drive is not mounted

Every enumerator of `data/` swallows ENOENT as "this channel has no videos", so
a sync of a channel on an unmounted platter reads the whole back catalogue as
undownloaded and hands the download lane an instruction to re-fetch hundreds of
gigabytes onto the volume that was too full to hold them.

`inspectChannelMedia` is the one module that can tell those two apart, and
`queueForSlugs.skip` already accepted a promise. ok and in-place are the healthy
answers; everything else is a skip carrying the inspector's own sentence, so the
readout names the drive instead of reporting a clean sweep over a channel
nothing could read.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

Diffstat:
Meditor/app/channels/actions.ts | 23++++++++++++++++++++++-
Meditor/e2e/channel-storage.spec.ts | 40++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/editor/app/channels/actions.ts b/editor/app/channels/actions.ts @@ -21,6 +21,7 @@ import { writeChannelConfig, } from "yt-dlp-transcript-common/controller/channels"; import { renameChannel } from "yt-dlp-transcript-common/controller/renameChannel"; +import { inspectChannelMedia } from "yt-dlp-transcript-common/lib/channelMedia"; import { channelMediaBusyReason } from "./lib/mediaBusy"; import { excludedDownloadIdSet, @@ -546,11 +547,31 @@ export async function syncAllChannelsAction( a.localeCompare(b), ); const outcome = await queueForSlugs(order, { - skip: (slug) => { + // AN UNMOUNTED DRIVE IS NOT AN EMPTY CHANNEL, and a sync is exactly the job + // that acts on that mistake. Every enumerator of `data/` swallows ENOENT as + // "no videos" (AGENTS.md), so a sync of a channel whose platter is not + // there reads the whole back catalogue as undownloaded and hands the + // download lane an instruction to re-fetch hundreds of gigabytes onto the + // volume that was too full to hold them. + // + // `inspectChannelMedia` is the one module that can tell the two apart. Two + // stats and at most one small JSON read per channel — cheap enough for a + // 68-channel pool, and the reason `queueForSlugs.skip` may be async. + // + // ok and in-place are the two healthy answers: the media is where config + // says, or there is no relocation at all. Everything else — `unreachable`, + // `in-transition`, `inconsistent` — is a skip with the inspector's own + // sentence, so the bulk bar names the drive rather than reporting a + // successful sweep over a channel nothing could read. + skip: async (slug) => { const config = bySlug.get(slug); if (!config?.url) return "no url"; if (isChannelPaused(priority, slug, "sync")) return "paused for sync"; if (active.has(slug)) return "already running"; + const media = await inspectChannelMedia(paths, slug, config); + if (media.status !== "ok" && media.status !== "in-place") { + return `media ${media.status}: ${media.detail ?? "not reachable"}`; + } return null; }, run: (slug) => syncAction(slug, undefined, opts?.fullSweep), diff --git a/editor/e2e/channel-storage.spec.ts b/editor/e2e/channel-storage.spec.ts @@ -3,6 +3,7 @@ import { lstat, mkdir, readdir, + rm, symlink, utimes, writeFile, @@ -766,3 +767,42 @@ test("the Storage panel evicts this channel's old clip windows", async ({ // a queued job, not part of the eviction. await expect.poll(clipsBytesOf, { timeout: 60_000 }).toBeLessThan(before); }); + +// SYNC ALL SKIPS A CHANNEL WHOSE DRIVE IS NOT THERE, and says which. +// +// This is the sharpest case for the guard in AGENTS.md: every enumerator of +// `data/` swallows ENOENT as "this channel has no videos", so a sync of a +// channel on an unmounted platter reads the whole back catalogue as +// undownloaded — and hands the download lane an instruction to re-fetch it all +// onto the volume that was too full to hold it in the first place. +// +// `inspectChannelMedia` is the one module that can tell "nothing downloaded" +// from "drive not mounted". A skip is not a failure: the bulk readout reports +// both numbers and names the channel with the inspector's own sentence. +test("Sync all skips a channel whose media drive is not mounted", async ({ + page, +}, testInfo) => { + test.setTimeout(90_000); + await resetData("one-youtube-channel-with-data"); + await writeSettings({ minFreeDiskGB: 0 }); + // A relocation whose drive went away: the link and the config agree with each + // other and with nothing on disk. Deliberately NOT created — an unmounted + // mountpoint whose parent is missing too is the honest version. + const target = join(testInfo.outputPath("never-mounted"), SLUG, "data"); + await rm(dataDir(), { recursive: true, force: true }); + await symlink(target, dataDir()); + await writeChannelConfig(SLUG, { dataDir: target }); + + await page.goto("/channels"); + await page.getByRole("button", { name: "sync every channel" }).click(); + const result = page.getByLabel("sync all result"); + await expect(result).toContainText(/Queued 0 . skipped 1/, { + timeout: 15_000, + }); + // THE REASON NAMES THE DRIVE, which is the only thing the operator can act + // on — "skipped 1" alone would read as a bug in the sweep. + await expect(result).toHaveAttribute( + "title", + new RegExp(`${SLUG}: media unreachable:.*drive not mounted`), + ); +});