feat: card-level cache
This commit is contained in:
@@ -6,7 +6,6 @@ declare global {
|
||||
var forked: boolean;
|
||||
}
|
||||
|
||||
|
||||
if (cluster.isPrimary) {
|
||||
if (!globalThis.forked) {
|
||||
for (let i = 0; i < 2; i++) cluster.fork();
|
||||
|
||||
+19
-5
@@ -1,5 +1,5 @@
|
||||
import { ImageResponse } from "@takumi-rs/image-response";
|
||||
import { file } from "bun";
|
||||
import { file, hash } from "bun";
|
||||
import { NotFoundError, status, t } from "elysia";
|
||||
import {
|
||||
fetchEnka,
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
InvalidFormatError,
|
||||
MaintenanceError,
|
||||
RatelimitError,
|
||||
TTLCache,
|
||||
} from "enka.ts";
|
||||
import { twj } from "tw-to-css";
|
||||
import type { App } from "@";
|
||||
@@ -19,6 +20,7 @@ import { TalentSvg } from "@/assets/talent";
|
||||
import { AssetManager, getEnkaAvatarStore } from "@/lib/assets";
|
||||
|
||||
const assets = new AssetManager();
|
||||
const cache = new TTLCache();
|
||||
|
||||
const font = file(fontFile);
|
||||
const shade = file(shadeSvg);
|
||||
@@ -41,7 +43,9 @@ export function card(app: App) {
|
||||
// const data = mockData;
|
||||
const [avatarStore, data] = await Promise.all([
|
||||
getEnkaAvatarStore().finally(() =>
|
||||
console.log(`${Date.now() - start}ms - Avatar store loaded`),
|
||||
console.log(
|
||||
`\n${Date.now() - start}ms - Avatar store loaded`,
|
||||
),
|
||||
),
|
||||
fetchEnka(uid, false).finally(() =>
|
||||
console.log(`${Date.now() - start}ms - Enka data loaded`),
|
||||
@@ -57,9 +61,14 @@ export function card(app: App) {
|
||||
const avatar = avatarStore[char.avatar.avatarId];
|
||||
if (!avatar)
|
||||
return status(
|
||||
500,
|
||||
400,
|
||||
"Unsupported character, avatar store doesn't have this character",
|
||||
);
|
||||
|
||||
const cacheKey = hash(JSON.stringify(data)).toString(36);
|
||||
const cached = cache.get<ImageResponse>(cacheKey);
|
||||
if (cached) return cached;
|
||||
|
||||
const resources = await Promise.all([
|
||||
...[...avatar.Consts, ...Object.values(avatar.Skills)].map(
|
||||
async (path) => ({
|
||||
@@ -80,7 +89,7 @@ export function card(app: App) {
|
||||
data,
|
||||
})),
|
||||
assets
|
||||
.fnCache("bg", () =>
|
||||
.fnCache(`bg-${avatar.Element}`, () =>
|
||||
generateBackground({
|
||||
element: avatar.Element,
|
||||
width: 1218,
|
||||
@@ -101,7 +110,7 @@ export function card(app: App) {
|
||||
char.propMap?.[1002].val ?? 1
|
||||
];
|
||||
|
||||
return new ImageResponse(
|
||||
const res = new ImageResponse(
|
||||
<div tw="relative text-[32.25px] text-white rounded-xl overflow-hidden">
|
||||
<div tw="aspect-[1218/508] h-full">
|
||||
<img
|
||||
@@ -259,6 +268,11 @@ export function card(app: App) {
|
||||
],
|
||||
},
|
||||
);
|
||||
queueMicrotask(() => {
|
||||
cache.set(cacheKey, res, 1000 * 60 * 60 * 24); // cache for 24 hour
|
||||
});
|
||||
|
||||
return res.clone();
|
||||
} catch (err) {
|
||||
if (err instanceof InvalidFormatError)
|
||||
return status(400, "Invalid UID format");
|
||||
|
||||
Reference in New Issue
Block a user