Skip to content
This repository was archived by the owner on Feb 3, 2025. It is now read-only.

Commit e9f6bfe

Browse files
committed
fix: remove ongoing download jobs if exist
1 parent a18d166 commit e9f6bfe

File tree

2 files changed

+47
-5
lines changed

2 files changed

+47
-5
lines changed

src/server/queue/download.ts

+41-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
11
import { Prisma } from '@prisma/client';
22
import { Job, Queue, Worker } from 'bullmq';
33
import { sanitizer } from '../../utils';
4+
import { logger } from '../../utils/logging';
45
import { prisma } from '../db/client';
5-
import { downloadChapter, getChapterFromLocal } from '../utils/mangal';
6+
import { downloadChapter, getChapterFromLocal, getMangaPath, removeManga } from '../utils/mangal';
67
import { notificationQueue } from './notify';
78

89
const mangaWithLibraryAndMetadata = Prisma.validator<Prisma.MangaArgs>()({
910
include: { library: true, metadata: true },
1011
});
1112

12-
export type MangaWithLibraryAndMetadata = Prisma.MangaGetPayload<typeof mangaWithLibraryAndMetadata>;
13+
type MangaWithLibraryAndMetadata = Prisma.MangaGetPayload<typeof mangaWithLibraryAndMetadata>;
14+
15+
const mangaWithChaptersAndLibrary = Prisma.validator<Prisma.MangaArgs>()({
16+
include: { chapters: true, library: true },
17+
});
18+
19+
type MangaWithChaptersAndLibrary = Prisma.MangaGetPayload<typeof mangaWithChaptersAndLibrary>;
1320
export interface IDownloadWorkerData {
1421
manga: MangaWithLibraryAndMetadata;
1522
chapterIndex: number;
@@ -19,8 +26,19 @@ export const downloadWorker = new Worker(
1926
'downloadQueue',
2027
async (job: Job) => {
2128
const { chapterIndex, manga }: IDownloadWorkerData = job.data;
29+
let filePath;
2230
try {
23-
const filePath = await downloadChapter(manga.title, manga.source, chapterIndex, manga.library.path);
31+
const mangaInDb = await prisma.manga.findUnique({ where: { id: manga.id } });
32+
if (!mangaInDb) {
33+
job.log(`Manga ${manga.title} with id ${manga.id} is removed from db.`);
34+
downloadWorker.on('completed', async ({ id }) => {
35+
if (id === job.id) {
36+
await job.remove();
37+
}
38+
});
39+
return;
40+
}
41+
filePath = await downloadChapter(manga.title, manga.source, chapterIndex, manga.library.path);
2442
const chapter = await getChapterFromLocal(filePath);
2543

2644
await prisma.chapter.deleteMany({
@@ -46,6 +64,10 @@ export const downloadWorker = new Worker(
4664
await job.updateProgress(100);
4765
} catch (err) {
4866
await job.log(`${err}`);
67+
if (err instanceof Prisma.PrismaClientKnownRequestError && err.code === 'P2003' && filePath) {
68+
await removeManga(getMangaPath(manga.library.path, manga.title));
69+
await job.log(`Removed ${manga.title} folder because it was not found in db`);
70+
}
4971
throw err;
5072
}
5173
},
@@ -71,3 +93,19 @@ export const downloadQueue = new Queue('downloadQueue', {
7193
},
7294
},
7395
});
96+
97+
export const removeDownloadJobs = async (manga: MangaWithChaptersAndLibrary) => {
98+
await Promise.all(
99+
manga.chapters.map(async (chapter) => {
100+
const jobId = `${sanitizer(manga.title)}_${chapter.index}_download`;
101+
try {
102+
const job = await downloadQueue.getJob(jobId);
103+
if (job) {
104+
await job.remove();
105+
}
106+
} catch (err) {
107+
logger.error(`job could not be cancelled. err: ${err}`);
108+
}
109+
}),
110+
);
111+
};

src/server/trpc/router/manga.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import path from 'path';
33
import { z } from 'zod';
44
import { isCronValid, sanitizer } from '../../../utils';
55
import { checkChaptersQueue, removeJob, schedule } from '../../queue/checkChapters';
6-
import { downloadQueue } from '../../queue/download';
6+
import { downloadQueue, downloadWorker, removeDownloadJobs } from '../../queue/download';
77
import {
88
bindTitleToAnilistId,
99
getAvailableSources,
@@ -89,9 +89,11 @@ export const mangaRouter = t.router({
8989
)
9090
.mutation(async ({ input, ctx }) => {
9191
const { id, shouldRemoveFiles } = input;
92+
await downloadWorker.pause(true);
9293
const removed = await ctx.prisma.manga.delete({
9394
include: {
9495
library: true,
96+
chapters: true,
9597
},
9698
where: {
9799
id,
@@ -102,11 +104,13 @@ export const mangaRouter = t.router({
102104
id: removed.metadataId,
103105
},
104106
});
107+
await removeJob(removed.title);
108+
await removeDownloadJobs(removed);
105109
if (shouldRemoveFiles === true) {
106110
const mangaPath = path.resolve(removed.library.path, sanitizer(removed.title));
107111
await removeManga(mangaPath);
108112
}
109-
await removeJob(removed.title);
113+
downloadWorker.resume();
110114
}),
111115
add: t.procedure
112116
.input(

0 commit comments

Comments
 (0)