diff --git a/packages/backend/deno.json b/packages/backend/deno.json index df5ca5d..7103153 100644 --- a/packages/backend/deno.json +++ b/packages/backend/deno.json @@ -5,7 +5,8 @@ "hono": "jsr:@hono/hono@^4.7.5", "zod": "npm:zod", "yup": "npm:yup", - "@crawler/net/videoInfo": "../crawler/net/getVideoInfo.ts" + "@crawler/net/videoInfo": "../crawler/net/getVideoInfo.ts", + "ioredis": "npm:ioredis" }, "tasks": { "dev": "deno serve --env-file=.env --allow-env --allow-net --allow-read --allow-write --allow-run --watch main.ts", diff --git a/packages/backend/main.ts b/packages/backend/main.ts index b9e5b72..31e4fcb 100644 --- a/packages/backend/main.ts +++ b/packages/backend/main.ts @@ -23,4 +23,4 @@ export default { fetch, } satisfies Deno.ServeDefaultExport; -export const VERSION = "0.4.0"; +export const VERSION = "0.4.1"; diff --git a/packages/backend/videoInfo.ts b/packages/backend/videoInfo.ts index 351b2de..8449c95 100644 --- a/packages/backend/videoInfo.ts +++ b/packages/backend/videoInfo.ts @@ -5,6 +5,11 @@ import { number, ValidationError } from "yup"; import { getVideoInfo, getVideoInfoByBV } from "@crawler/net/videoInfo"; import { idSchema } from "./snapshots.ts"; import type { VideoInfoData } from "../crawler/net/bilibili.d.ts"; +import { Redis } from "ioredis"; +import { NetSchedulerError } from "../crawler/mq/scheduler.ts"; + +const redis = new Redis({ maxRetriesPerRequest: null }); +const CACHE_EXPIRATION_SECONDS = 60; type ContextType = Context; @@ -17,6 +22,14 @@ export const videoInfoHandler = createHandlers(async (c: ContextType) => { } else if (await number().isValid(videoId)) { videoId = parseInt(videoId); } + + const cacheKey = `cvsa:videoInfo:${videoId}`; + const cachedData = await redis.get(cacheKey); + + if (cachedData) { + return c.json(JSON.parse(cachedData)); + } + let result: VideoInfoData | number; if (typeof videoId === "number") { result = await getVideoInfo(videoId, "getVideoInfo"); @@ -28,12 +41,16 @@ export const videoInfoHandler = createHandlers(async (c: ContextType) => { return c.json({ message: "Error fetching video info", code: result }, 500); } + await redis.setex(cacheKey, CACHE_EXPIRATION_SECONDS, JSON.stringify(result)); + return c.json(result); } catch (e) { if (e instanceof ValidationError) { return c.json({ message: "Invalid query parameters", errors: e.errors }, 400); + } else if (e instanceof NetSchedulerError) { + return c.json({ message: "Error fetching video info", code: e.code }, 500); } else { return c.json({ message: "Unhandled error", error: e }, 500); } } -}); +}); \ No newline at end of file