Fix issue with videos getting stuck due to other videos failing
This commit is contained in:
parent
d2f9045084
commit
0ba2d85006
|
|
@ -1,7 +1,11 @@
|
|||
import cron from 'node-cron';
|
||||
import { videoOperations, configOperations, channelOperations } from '../db/database';
|
||||
import { downloadVideo, getChannelVideos } from './ytdlp';
|
||||
import { DownloadProgress } from '../types';
|
||||
import cron from "node-cron";
|
||||
import {
|
||||
videoOperations,
|
||||
configOperations,
|
||||
channelOperations,
|
||||
} from "../db/database";
|
||||
import { downloadVideo, getChannelVideos } from "./ytdlp";
|
||||
import { DownloadProgress } from "../types";
|
||||
|
||||
let schedulerTask: cron.ScheduledTask | null = null;
|
||||
let isDownloading = false;
|
||||
|
|
@ -11,7 +15,10 @@ function getRandomVariance(varianceMinutes: number): number {
|
|||
return Math.floor(Math.random() * varianceMinutes * 2) - varianceMinutes;
|
||||
}
|
||||
|
||||
function calculateNextRun(intervalMinutes: number, varianceMinutes: number): Date {
|
||||
function calculateNextRun(
|
||||
intervalMinutes: number,
|
||||
varianceMinutes: number,
|
||||
): Date {
|
||||
const variance = getRandomVariance(varianceMinutes);
|
||||
const totalMinutes = intervalMinutes + variance;
|
||||
|
||||
|
|
@ -22,22 +29,22 @@ function calculateNextRun(intervalMinutes: number, varianceMinutes: number): Dat
|
|||
|
||||
async function downloadNextVideo() {
|
||||
if (isDownloading) {
|
||||
console.log('Already downloading a video, skipping...');
|
||||
console.log("Already downloading a video, skipping...");
|
||||
return;
|
||||
}
|
||||
|
||||
isDownloading = true;
|
||||
currentProgress = null;
|
||||
|
||||
const video = videoOperations.getNextPending();
|
||||
if (!video) {
|
||||
console.log("No pending videos to download");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
isDownloading = true;
|
||||
currentProgress = null;
|
||||
|
||||
const video = videoOperations.getNextPending();
|
||||
if (!video) {
|
||||
console.log('No pending videos to download');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`Starting download: ${video.title} (${video.videoId})`);
|
||||
videoOperations.updateStatus(video.id, 'downloading');
|
||||
videoOperations.updateStatus(video.id, "downloading");
|
||||
|
||||
const result = await downloadVideo(video.videoId, video.url, {
|
||||
onProgress: (progress, speed, eta) => {
|
||||
|
|
@ -45,23 +52,21 @@ async function downloadNextVideo() {
|
|||
videoId: video.videoId,
|
||||
progress,
|
||||
speed,
|
||||
eta
|
||||
eta,
|
||||
};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
videoOperations.markCompleted(video.id, result.filePath, result.fileSize);
|
||||
console.log(`Download completed: ${video.title}`);
|
||||
currentProgress = null;
|
||||
|
||||
} catch (error) {
|
||||
console.error('Download error:', error);
|
||||
const video = videoOperations.getNextPending();
|
||||
console.error("Download error:", error);
|
||||
if (video) {
|
||||
videoOperations.updateStatus(
|
||||
video.id,
|
||||
'failed',
|
||||
error instanceof Error ? error.message : 'Unknown error'
|
||||
"failed",
|
||||
error instanceof Error ? error.message : "Unknown error",
|
||||
);
|
||||
}
|
||||
currentProgress = null;
|
||||
|
|
@ -71,7 +76,7 @@ async function downloadNextVideo() {
|
|||
}
|
||||
|
||||
async function checkChannelsForNewVideos() {
|
||||
const channels = channelOperations.getAll().filter(c => c.active);
|
||||
const channels = channelOperations.getAll().filter((c) => c.active);
|
||||
|
||||
for (const channel of channels) {
|
||||
try {
|
||||
|
|
@ -81,7 +86,7 @@ async function checkChannelsForNewVideos() {
|
|||
for (const videoInfo of videos) {
|
||||
// Check if video already exists
|
||||
const existingVideos = videoOperations.getAll();
|
||||
const exists = existingVideos.some(v => v.videoId === videoInfo.id);
|
||||
const exists = existingVideos.some((v) => v.videoId === videoInfo.id);
|
||||
|
||||
if (!exists) {
|
||||
console.log(`Found new video: ${videoInfo.title}`);
|
||||
|
|
@ -94,10 +99,10 @@ async function checkChannelsForNewVideos() {
|
|||
duration: videoInfo.duration,
|
||||
thumbnail: videoInfo.thumbnail,
|
||||
uploadDate: videoInfo.uploadDate,
|
||||
status: 'pending',
|
||||
status: "pending",
|
||||
filePath: null,
|
||||
fileSize: null,
|
||||
error: null
|
||||
error: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -111,36 +116,38 @@ async function checkChannelsForNewVideos() {
|
|||
|
||||
export function startScheduler() {
|
||||
if (schedulerTask) {
|
||||
console.log('Scheduler already running');
|
||||
console.log("Scheduler already running");
|
||||
return;
|
||||
}
|
||||
|
||||
const config = configOperations.getAll();
|
||||
const enabled = config.enabled === 'true';
|
||||
const enabled = config.enabled === "true";
|
||||
|
||||
if (!enabled) {
|
||||
console.log('Scheduler is disabled');
|
||||
console.log("Scheduler is disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
const intervalMinutes = parseFloat(config.intervalMinutes || '180'); // Default 180 minutes (3 hours)
|
||||
const varianceMinutes = parseFloat(config.varianceMinutes || '30');
|
||||
const intervalMinutes = parseFloat(config.intervalMinutes || "180"); // Default 180 minutes (3 hours)
|
||||
const varianceMinutes = parseFloat(config.varianceMinutes || "30");
|
||||
|
||||
console.log(`Starting scheduler: ${intervalMinutes}min ±${varianceMinutes}min`);
|
||||
console.log(
|
||||
`Starting scheduler: ${intervalMinutes}min ±${varianceMinutes}min`,
|
||||
);
|
||||
|
||||
// Check for new videos every hour
|
||||
schedulerTask = cron.schedule('0 * * * *', async () => {
|
||||
console.log('Checking channels for new videos...');
|
||||
schedulerTask = cron.schedule("0 * * * *", async () => {
|
||||
console.log("Checking channels for new videos...");
|
||||
await checkChannelsForNewVideos();
|
||||
});
|
||||
|
||||
// Download next video with variable interval
|
||||
async function scheduleNextDownload() {
|
||||
const config = configOperations.getAll();
|
||||
const enabled = config.enabled === 'true';
|
||||
const enabled = config.enabled === "true";
|
||||
|
||||
if (!enabled) {
|
||||
console.log('Scheduler disabled, stopping...');
|
||||
console.log("Scheduler disabled, stopping...");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -148,8 +155,8 @@ export function startScheduler() {
|
|||
await downloadNextVideo();
|
||||
|
||||
// AFTER download completes, calculate next run
|
||||
const intervalMinutes = parseFloat(config.intervalMinutes || '180'); // Default 180 minutes (3 hours)
|
||||
const varianceMinutes = parseFloat(config.varianceMinutes || '30');
|
||||
const intervalMinutes = parseFloat(config.intervalMinutes || "180"); // Default 180 minutes (3 hours)
|
||||
const varianceMinutes = parseFloat(config.varianceMinutes || "30");
|
||||
const nextRun = calculateNextRun(intervalMinutes, varianceMinutes);
|
||||
|
||||
console.log(`Next download scheduled for: ${nextRun.toLocaleString()}`);
|
||||
|
|
@ -161,14 +168,14 @@ export function startScheduler() {
|
|||
// Start the first download cycle
|
||||
scheduleNextDownload();
|
||||
|
||||
console.log('Scheduler started');
|
||||
console.log("Scheduler started");
|
||||
}
|
||||
|
||||
export function stopScheduler() {
|
||||
if (schedulerTask) {
|
||||
schedulerTask.stop();
|
||||
schedulerTask = null;
|
||||
console.log('Scheduler stopped');
|
||||
console.log("Scheduler stopped");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -181,11 +188,11 @@ export function getSchedulerStatus() {
|
|||
const config = configOperations.getAll();
|
||||
return {
|
||||
running: schedulerTask !== null,
|
||||
enabled: config.enabled === 'true',
|
||||
intervalMinutes: parseFloat(config.intervalMinutes || '180'),
|
||||
varianceMinutes: parseFloat(config.varianceMinutes || '30'),
|
||||
enabled: config.enabled === "true",
|
||||
intervalMinutes: parseFloat(config.intervalMinutes || "180"),
|
||||
varianceMinutes: parseFloat(config.varianceMinutes || "30"),
|
||||
isDownloading,
|
||||
currentProgress
|
||||
currentProgress,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue