mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-11-26 16:25:11 -05:00
Fix deadlock on image downloading
This commit is contained in:
parent
20ab1dae6c
commit
a4f5ef33ff
@ -152,8 +152,7 @@ async function processOne() {
|
|||||||
span.setStatus({ code: SpanStatusCode.ERROR });
|
span.setStatus({ code: SpanStatusCode.ERROR });
|
||||||
}
|
}
|
||||||
console.error("Failed to download image", img.url, err.message);
|
console.error("Failed to download image", img.url, err.message);
|
||||||
// don't use the transaction here, it can be aborted.
|
await tx
|
||||||
await db
|
|
||||||
.update(mqueue)
|
.update(mqueue)
|
||||||
.set({ attempt: sql`${mqueue.attempt}+1` })
|
.set({ attempt: sql`${mqueue.attempt}+1` })
|
||||||
.where(eq(mqueue.id, item.id));
|
.where(eq(mqueue.id, item.id));
|
||||||
|
|||||||
48
api/tests/helpers/collections-helper.ts
Normal file
48
api/tests/helpers/collections-helper.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { buildUrl } from "tests/utils";
|
||||||
|
import { handlers } from "~/base";
|
||||||
|
import { getJwtHeaders } from "./jwt";
|
||||||
|
|
||||||
|
export const getCollection = async (
|
||||||
|
id: string,
|
||||||
|
{
|
||||||
|
langs,
|
||||||
|
...query
|
||||||
|
}: { langs?: string; preferOriginal?: boolean; with?: string[] },
|
||||||
|
) => {
|
||||||
|
const resp = await handlers.handle(
|
||||||
|
new Request(buildUrl(`collections/${id}`, query), {
|
||||||
|
method: "GET",
|
||||||
|
headers: langs
|
||||||
|
? {
|
||||||
|
"Accept-Language": langs,
|
||||||
|
...(await getJwtHeaders()),
|
||||||
|
}
|
||||||
|
: await getJwtHeaders(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const body = await resp.json();
|
||||||
|
return [resp, body] as const;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getCollections = async ({
|
||||||
|
langs,
|
||||||
|
...query
|
||||||
|
}: {
|
||||||
|
langs?: string;
|
||||||
|
preferOriginal?: boolean;
|
||||||
|
with?: string[];
|
||||||
|
}) => {
|
||||||
|
const resp = await handlers.handle(
|
||||||
|
new Request(buildUrl("collections", query), {
|
||||||
|
method: "GET",
|
||||||
|
headers: langs
|
||||||
|
? {
|
||||||
|
"Accept-Language": langs,
|
||||||
|
...(await getJwtHeaders()),
|
||||||
|
}
|
||||||
|
: await getJwtHeaders(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
const body = await resp.json();
|
||||||
|
return [resp, body] as const;
|
||||||
|
};
|
||||||
@ -1,4 +1,5 @@
|
|||||||
export * from "~/base";
|
export * from "~/base";
|
||||||
|
export * from "./collections-helper";
|
||||||
export * from "./movies-helper";
|
export * from "./movies-helper";
|
||||||
export * from "./series-helper";
|
export * from "./series-helper";
|
||||||
export * from "./shows-helper";
|
export * from "./shows-helper";
|
||||||
|
|||||||
@ -1,19 +1,22 @@
|
|||||||
import { describe, expect, it } from "bun:test";
|
import { beforeAll, describe, expect, it } from "bun:test";
|
||||||
import { eq } from "drizzle-orm";
|
import { and, eq, sql } from "drizzle-orm";
|
||||||
|
import { createMovie, createSerie } from "tests/helpers";
|
||||||
|
import { expectStatus } from "tests/utils";
|
||||||
import { defaultBlurhash, processImages } from "~/controllers/seed/images";
|
import { defaultBlurhash, processImages } from "~/controllers/seed/images";
|
||||||
import { db } from "~/db";
|
import { db } from "~/db";
|
||||||
import { mqueue, shows, staff, studios, videos } from "~/db/schema";
|
import { mqueue, shows, staff, studios, videos } from "~/db/schema";
|
||||||
import { madeInAbyss } from "~/models/examples";
|
import { dune, madeInAbyss } from "~/models/examples";
|
||||||
import { createSerie } from "../helpers";
|
|
||||||
|
|
||||||
describe("images", () => {
|
describe("images", () => {
|
||||||
it("Create a serie download images", async () => {
|
beforeAll(async () => {
|
||||||
await db.delete(shows);
|
await db.delete(shows);
|
||||||
await db.delete(studios);
|
await db.delete(studios);
|
||||||
await db.delete(staff);
|
await db.delete(staff);
|
||||||
await db.delete(videos);
|
await db.delete(videos);
|
||||||
await db.delete(mqueue);
|
await db.delete(mqueue);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Create a serie download images", async () => {
|
||||||
await createSerie(madeInAbyss);
|
await createSerie(madeInAbyss);
|
||||||
const release = await processImages();
|
const release = await processImages();
|
||||||
// remove notifications to prevent other images to be downloaded (do not curl 20000 images for nothing)
|
// remove notifications to prevent other images to be downloaded (do not curl 20000 images for nothing)
|
||||||
@ -26,4 +29,29 @@ describe("images", () => {
|
|||||||
expect(ret!.original.poster!.blurhash).toBeString();
|
expect(ret!.original.poster!.blurhash).toBeString();
|
||||||
expect(ret!.original.poster!.blurhash).not.toBe(defaultBlurhash);
|
expect(ret!.original.poster!.blurhash).not.toBe(defaultBlurhash);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Download 404 image", async () => {
|
||||||
|
const [ret, body] = await createMovie({
|
||||||
|
...dune,
|
||||||
|
translations: {
|
||||||
|
en: {
|
||||||
|
...dune.translations.en,
|
||||||
|
poster: "https://www.google.com/404",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expectStatus(ret, body).toBe(201);
|
||||||
|
|
||||||
|
const release = await processImages();
|
||||||
|
// remove notifications to prevent other images to be downloaded (do not curl 20000 images for nothing)
|
||||||
|
release();
|
||||||
|
|
||||||
|
const failed = await db.query.mqueue.findFirst({
|
||||||
|
where: and(
|
||||||
|
eq(mqueue.kind, "image"),
|
||||||
|
eq(sql`${mqueue.message}->>'url'`, "https://www.google.com/404"),
|
||||||
|
),
|
||||||
|
});
|
||||||
|
expect(failed!.attempt).toBe(5);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user