diff --git a/src/controllers/watch-status/anilist.ts b/src/controllers/watch-status/anilist.ts index dc65e73..28a5077 100644 --- a/src/controllers/watch-status/anilist.ts +++ b/src/controllers/watch-status/anilist.ts @@ -30,19 +30,11 @@ const DeleteMediaListEntryMutation = graphql(` } `); -/** Updates the watch status for a title on Anilist. If the token is null, the watch status will not be updated. - * - * @returns true if the watch status was updated or if the token was null, false if it was not - */ -export async function maybeUpdateWatchStatusOnAnilist( +export async function updateWatchStatusOnAnilist( titleId: number, watchStatus: WatchStatus | null, - aniListToken: string | undefined, + aniListToken: string, ) { - if (!aniListToken) { - return true; - } - const client = new GraphQLClient("https://graphql.anilist.co/"); const headers = new Headers({ Authorization: `Bearer ${aniListToken}` }); diff --git a/src/controllers/watch-status/index.spec.ts b/src/controllers/watch-status/index.spec.ts index 1eef82a..d158025 100644 --- a/src/controllers/watch-status/index.spec.ts +++ b/src/controllers/watch-status/index.spec.ts @@ -22,8 +22,6 @@ vi.mock("~/mocks", () => ({ describe("requests the /watch-status route", () => { const db = getTestDb(env); let app: typeof import("../../../src/index").app; - let maybeUpdateWatchStatusOnAnilist: any; - let queueTask: any; let maybeScheduleNextAiringEpisode: any; let removeTask: any; @@ -31,10 +29,6 @@ describe("requests the /watch-status route", () => { await resetTestDb(db); vi.resetModules(); - vi.doMock("./anilist", () => ({ - maybeUpdateWatchStatusOnAnilist: vi.fn().mockResolvedValue(undefined), - })); - vi.doMock("~/libs/tasks/queueTask", () => ({ queueTask: vi.fn().mockResolvedValue(undefined), })); @@ -52,10 +46,6 @@ describe("requests the /watch-status route", () => { })); app = (await import("~/index")).app; - maybeUpdateWatchStatusOnAnilist = ( - await import("~/controllers/watch-status/anilist") - ).maybeUpdateWatchStatusOnAnilist; - queueTask = (await import("~/libs/tasks/queueTask")).queueTask; removeTask = (await import("~/libs/tasks/removeTask")).removeTask; maybeScheduleNextAiringEpisode = ( await import("~/libs/maybeScheduleNextAiringEpisode") @@ -119,34 +109,6 @@ describe("requests the /watch-status route", () => { expect(res.status).toBe(500); }); - it("saving title, Anilist request fails, should succeed", async () => { - vi.mocked(maybeUpdateWatchStatusOnAnilist).mockRejectedValue( - new Error("Anilist failed"), - ); - - const res = await app.request( - "/watch-status", - { - method: "POST", - headers: new Headers({ - "x-anilist-token": "asd", - "Content-Type": "application/json", - }), - body: JSON.stringify({ - deviceId: "123", - watchStatus: "CURRENT", - titleId: -1, - }), - }, - env, - ); - - await expect(res.json()).resolves.toEqual({ success: true }); - expect(res.status).toBe(200); - // Should queue task if direct update fails - expect(queueTask).toHaveBeenCalled(); - }); - it("watch status is null, should succeed", async () => { const res = await app.request( "/watch-status", diff --git a/src/controllers/watch-status/index.ts b/src/controllers/watch-status/index.ts index 5d585ee..6b313dd 100644 --- a/src/controllers/watch-status/index.ts +++ b/src/controllers/watch-status/index.ts @@ -16,8 +16,6 @@ import { } from "~/types/schema"; import { WatchStatus } from "~/types/title/watchStatus"; -import { maybeUpdateWatchStatusOnAnilist } from "./anilist"; - const app = new OpenAPIHono(); const UpdateWatchStatusRequest = z.object({ @@ -109,30 +107,16 @@ app.openapi(route, async (c) => { } } - try { - await maybeUpdateWatchStatusOnAnilist( - Number(titleId), + await queueTask( + "ANILIST_UPDATES", + { + deviceId, watchStatus, - aniListToken, - ); - } catch (error) { - console.error("Failed to update watch status on Anilist"); - console.error(error); - if (isRetrying) { - return c.json(ErrorResponse, { status: 500 }); - } - - await queueTask( - "ANILIST_UPDATES", - { - deviceId, - watchStatus, - titleId, - updateType: AnilistUpdateType.UpdateWatchStatus, - }, - { req: c.req, scheduleConfig: { delay: { minute: 1 } } }, - ); - } + titleId, + updateType: AnilistUpdateType.UpdateWatchStatus, + }, + { req: c.req, scheduleConfig: { delay: { minute: 1 } } }, + ); return c.json(SuccessResponse, { status: 200 }); }); diff --git a/src/index.ts b/src/index.ts index af8bc7d..60453d2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import { maybeUpdateLastConnectedAt } from "~/controllers/maybeUpdateLastConnect import type { QueueName } from "~/libs/tasks/queueName.ts"; import { onNewEpisode } from "./controllers/internal/new-episode"; +import { AnilistUpdateType } from "./libs/anilist/updateType"; import type { QueueBody } from "./libs/tasks/queueTask"; export const app = new OpenAPIHono<{ Bindings: Env }>(); @@ -74,7 +75,30 @@ export default { async queue(batch) { switch (batch.queue as QueueName) { case "ANILIST_UPDATES": - batch.retryAll(); + for (const message of ( + batch as MessageBatch + ).messages) { + switch (message.body.updateType) { + case AnilistUpdateType.UpdateWatchStatus: + if (!message.body[AnilistUpdateType.UpdateWatchStatus]) { + throw new Error( + `Discarding update, unknown body ${JSON.stringify(message.body)}`, + ); + } + + const { updateWatchStatusOnAnilist } = + await import("~/controllers/watch-status/anilist"); + const payload = message.body[AnilistUpdateType.UpdateWatchStatus]; + await updateWatchStatusOnAnilist( + payload.titleId, + payload.watchStatus, + payload.aniListToken, + ); + break; + } + + message.ack(); + } break; case "NEW_EPISODE": for (const message of (batch as MessageBatch) @@ -89,9 +113,8 @@ export default { } }, async scheduled(event, env, ctx) { - const { processDelayedTasks } = await import( - "~/libs/tasks/processDelayedTasks" - ); + const { processDelayedTasks } = + await import("~/libs/tasks/processDelayedTasks"); await processDelayedTasks(env, ctx); }, } satisfies ExportedHandler; diff --git a/src/libs/tasks/queueTask.ts b/src/libs/tasks/queueTask.ts index e1ff0e5..83f4ec1 100644 --- a/src/libs/tasks/queueTask.ts +++ b/src/libs/tasks/queueTask.ts @@ -9,9 +9,11 @@ import type { QueueName } from "./queueName"; export type QueueBody = { ANILIST_UPDATES: { - deviceId: string; - watchStatus: WatchStatus | null; - titleId: number; + [AnilistUpdateType.UpdateWatchStatus]: { + titleId: number; + watchStatus: WatchStatus | null; + aniListToken: string; + }; updateType: AnilistUpdateType; }; NEW_EPISODE: { aniListId: number; episodeNumber: number };