feat: a ton of caching
This commit is contained in:
+9
-7
@@ -2,8 +2,16 @@ import cluster from "node:cluster";
|
||||
import process from "node:process";
|
||||
import { AssetManager } from "./lib/assets";
|
||||
|
||||
declare global {
|
||||
var forked: boolean;
|
||||
}
|
||||
|
||||
|
||||
if (cluster.isPrimary) {
|
||||
for (let i = 0; i < 2; i++) cluster.fork();
|
||||
if (!globalThis.forked) {
|
||||
for (let i = 0; i < 2; i++) cluster.fork();
|
||||
globalThis.forked = true;
|
||||
}
|
||||
|
||||
queueMicrotask(async () => {
|
||||
const assets = new AssetManager();
|
||||
@@ -13,12 +21,6 @@ if (cluster.isPrimary) {
|
||||
assets.getMissingAssets();
|
||||
}, 86400000); // refresh assets every 24 hours
|
||||
});
|
||||
|
||||
import.meta.hot.dispose(() => {
|
||||
for (const worker of Object.values(cluster.workers ?? {})) {
|
||||
worker?.kill();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await import("./server");
|
||||
console.log(`Worker ${process.pid} started`);
|
||||
|
||||
@@ -54,6 +54,39 @@ export class AssetManager {
|
||||
queueMicrotask(() => write(local, data));
|
||||
return data;
|
||||
}
|
||||
|
||||
async hook(
|
||||
path: string,
|
||||
cb: (
|
||||
data: ArrayBuffer,
|
||||
) => Promise<ArrayBuffer | Buffer> | ArrayBuffer | Buffer,
|
||||
): Promise<ArrayBuffer | Buffer> {
|
||||
const key = `${path}-transformed`;
|
||||
return this.fnCache(key, async () => {
|
||||
const data = await this.load(path);
|
||||
return cb(data);
|
||||
});
|
||||
}
|
||||
|
||||
async fnCache(
|
||||
key: string,
|
||||
get: () => Promise<ArrayBuffer | Buffer> | ArrayBuffer | Buffer,
|
||||
) {
|
||||
const cacheKey = join("store", hash(`${key}-fnCache`).toString(36));
|
||||
if (this.cache.has(cacheKey)) return this.cache.get(cacheKey)!;
|
||||
const cached = file(cacheKey);
|
||||
if (await cached.exists()) return cached.arrayBuffer();
|
||||
|
||||
const returned = await get();
|
||||
this.cache.set(
|
||||
cacheKey,
|
||||
returned instanceof ArrayBuffer
|
||||
? returned
|
||||
: (returned.buffer as ArrayBuffer),
|
||||
);
|
||||
queueMicrotask(() => write(file(cacheKey), returned));
|
||||
return returned;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getEnkaAvatarStore(): Promise<AvatarStore> {
|
||||
|
||||
+16
-11
@@ -68,24 +68,29 @@ export function card(app: App) {
|
||||
}),
|
||||
),
|
||||
assets
|
||||
.load(
|
||||
.hook(
|
||||
avatar.SideIconName.replace(
|
||||
"AvatarIcon_Side",
|
||||
"Gacha_AvatarImg",
|
||||
),
|
||||
(buf) => featherImage(buf, [0, 0.3, 0, 0]),
|
||||
)
|
||||
.then(async (buf) => ({
|
||||
.then(async (data) => ({
|
||||
src: "/avatar",
|
||||
data: await featherImage(buf, [0, 0.3, 0, 0]),
|
||||
data,
|
||||
})),
|
||||
assets
|
||||
.fnCache("bg", () =>
|
||||
generateBackground({
|
||||
element: avatar.Element,
|
||||
width: 1218,
|
||||
height: 508,
|
||||
}).then((r) => r.canvas.toBuffer("image/webp")),
|
||||
)
|
||||
.then((data) => ({
|
||||
src: "/bg",
|
||||
data,
|
||||
})),
|
||||
generateBackground({
|
||||
element: avatar.Element,
|
||||
width: 1218,
|
||||
height: 508,
|
||||
}).then((r) => ({
|
||||
src: "/bg",
|
||||
data: r.canvas.toBuffer("image/webp"),
|
||||
})),
|
||||
]);
|
||||
console.log(
|
||||
`${Date.now() - start}ms - Image resources loaded\n${resources.map((r) => `- ${r.src} ${(r.data.byteLength / 1000).toFixed(2)}Kb`).join("\n")}`,
|
||||
|
||||
Reference in New Issue
Block a user