Run the title catch-up in its own YouTube lane

This commit is contained in:
Fisto
2026-09-17 14:25:08 +02:00
parent 8befc05591
commit 9481286169
16 changed files with 495 additions and 82 deletions
+25
View File
@@ -17,6 +17,8 @@ import {
ScrapeEngine,
ScrapeStore,
scrapeDir,
TitleLane,
type TitleLaneStatus,
snowflakeFromIso,
resolveDbRoot,
type MediaKind,
@@ -171,6 +173,7 @@ export class MediaService {
private readonly rootDir = resolveDbRoot();
private readonly engine: ScrapeEngine;
private readonly backfill: BackfillQueue;
private readonly titles: TitleLane;
private bot: BotClient | null = null;
private botFetcher: SlopbotFetcher | null = null;
@@ -214,6 +217,14 @@ export class MediaService {
log: line => this.deps.log?.(line)
});
// The title catch-up lane talks to YouTube only, so it runs beside the backfill queue.
// It auto-starts because it is a one-time catch-up: with nothing pending it exits at once.
this.titles = new TitleLane(this.engine, {
rootDir: this.rootDir,
log: line => this.deps.log?.(line)
});
this.titles.start();
const stale = this.engine.reconcileStaleJobs();
if (stale.length) {
this.deps.log?.(`paused ${stale.length} stale scrape(s) left running by a previous daemon`);
@@ -268,6 +279,20 @@ export class MediaService {
};
}
titleStatus(): TitleLaneStatus {
return this.titles.status();
}
startTitles(): TitleLaneStatus {
this.titles.start();
return this.titles.status();
}
pauseTitles(): TitleLaneStatus {
this.titles.pause();
return this.titles.status();
}
startBackfill(chatId?: string): BackfillStatus {
this.backfill.start(chatId);
return this.backfillStatus();
+21
View File
@@ -835,6 +835,27 @@ export function startWebUi(deps: WebUiDeps): WebUiHandle {
})
);
app.get(
"/api/media/titles",
wrap(async (_req, res) => {
res.json({ ok: true, result: deps.media.titleStatus() });
})
);
app.post(
"/api/media/titles/start",
wrap(async (_req, res) => {
res.json({ ok: true, result: deps.media.startTitles() });
})
);
app.post(
"/api/media/titles/pause",
wrap(async (_req, res) => {
res.json({ ok: true, result: deps.media.pauseTitles() });
})
);
app.post(
"/api/media/backfill/start",
wrap(async (req, res) => {