add: cache in videoInfo API

This commit is contained in:
alikia2x (寒寒) 2025-04-07 21:37:59 +08:00
parent 71ed0bd66b
commit 8e7a1c3076
Signed by: alikia2x
GPG Key ID: 56209E0CCD8420C6
3 changed files with 21 additions and 3 deletions

View File

@ -5,7 +5,8 @@
"hono": "jsr:@hono/hono@^4.7.5", "hono": "jsr:@hono/hono@^4.7.5",
"zod": "npm:zod", "zod": "npm:zod",
"yup": "npm:yup", "yup": "npm:yup",
"@crawler/net/videoInfo": "../crawler/net/getVideoInfo.ts" "@crawler/net/videoInfo": "../crawler/net/getVideoInfo.ts",
"ioredis": "npm:ioredis"
}, },
"tasks": { "tasks": {
"dev": "deno serve --env-file=.env --allow-env --allow-net --allow-read --allow-write --allow-run --watch main.ts", "dev": "deno serve --env-file=.env --allow-env --allow-net --allow-read --allow-write --allow-run --watch main.ts",

View File

@ -23,4 +23,4 @@ export default {
fetch, fetch,
} satisfies Deno.ServeDefaultExport; } satisfies Deno.ServeDefaultExport;
export const VERSION = "0.4.0"; export const VERSION = "0.4.1";

View File

@ -5,6 +5,11 @@ import { number, ValidationError } from "yup";
import { getVideoInfo, getVideoInfoByBV } from "@crawler/net/videoInfo"; import { getVideoInfo, getVideoInfoByBV } from "@crawler/net/videoInfo";
import { idSchema } from "./snapshots.ts"; import { idSchema } from "./snapshots.ts";
import type { VideoInfoData } from "../crawler/net/bilibili.d.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<BlankEnv, "/video/:id/info", BlankInput>; type ContextType = Context<BlankEnv, "/video/:id/info", BlankInput>;
@ -17,6 +22,14 @@ export const videoInfoHandler = createHandlers(async (c: ContextType) => {
} else if (await number().isValid(videoId)) { } else if (await number().isValid(videoId)) {
videoId = parseInt(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; let result: VideoInfoData | number;
if (typeof videoId === "number") { if (typeof videoId === "number") {
result = await getVideoInfo(videoId, "getVideoInfo"); 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); 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); return c.json(result);
} catch (e) { } catch (e) {
if (e instanceof ValidationError) { if (e instanceof ValidationError) {
return c.json({ message: "Invalid query parameters", errors: e.errors }, 400); 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 { } else {
return c.json({ message: "Unhandled error", error: e }, 500); return c.json({ message: "Unhandled error", error: e }, 500);
} }
} }
}); });