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