Optimize admin performance and split render surface
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { createHash } from "node:crypto";
|
||||
import { watch } from "node:fs";
|
||||
import { mkdir, rm, writeFile } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
@@ -62,6 +63,56 @@ const fileExtensionFor = (mimeType: string, filename?: string) => {
|
||||
return fallback || ".bin";
|
||||
};
|
||||
|
||||
const createRevision = (value: unknown) => createHash("sha1").update(JSON.stringify(value)).digest("hex");
|
||||
|
||||
const getProgramRevision = (state: Awaited<ReturnType<StateStore["read"]>>) =>
|
||||
createRevision({
|
||||
cues: state.cues.map((cue) => ({
|
||||
id: cue.id,
|
||||
orderIndex: cue.orderIndex,
|
||||
sceneDefinitionId: cue.sceneDefinitionId,
|
||||
effectPresetId: cue.effectPresetId,
|
||||
updated: [cue.transitionIn, cue.transitionOut, cue.assetIds, cue.notes, cue.triggerMode, cue.durationMs, cue.nextCueId, cue.collectionId]
|
||||
})),
|
||||
safeSceneCueId: state.showConfig.safeSceneCueId
|
||||
});
|
||||
|
||||
const getLibraryRevision = (state: Awaited<ReturnType<StateStore["read"]>>) =>
|
||||
createRevision({
|
||||
photoAssets: state.photoAssets.map((asset) => ({
|
||||
id: asset.id,
|
||||
submissionId: asset.submissionId,
|
||||
moderationStatus: asset.moderationStatus,
|
||||
processingStatus: asset.processingStatus,
|
||||
thumbKey: asset.thumbKey,
|
||||
previewKey: asset.previewKey,
|
||||
renderKey: asset.renderKey,
|
||||
approvedAt: asset.approvedAt
|
||||
})),
|
||||
submissions: state.submissions.map((submission) => ({
|
||||
id: submission.id,
|
||||
status: submission.status,
|
||||
contributorName: submission.contributorName,
|
||||
lovedOneName: submission.lovedOneName,
|
||||
displayName: submission.displayName,
|
||||
caption: submission.caption,
|
||||
promptAnswer: submission.promptAnswer,
|
||||
notes: submission.notes,
|
||||
source: submission.source
|
||||
})),
|
||||
collections: state.collections.map((collection) => ({
|
||||
id: collection.id,
|
||||
assetIds: collection.assetIds,
|
||||
coverAssetId: collection.coverAssetId
|
||||
}))
|
||||
});
|
||||
|
||||
const createAdminBootstrapPayload = (state: Awaited<ReturnType<StateStore["read"]>>) => ({
|
||||
...state,
|
||||
libraryRevision: getLibraryRevision(state),
|
||||
programRevision: getProgramRevision(state)
|
||||
});
|
||||
|
||||
const normalizeMimeType = (mimeType: string | undefined, filename?: string) => {
|
||||
const normalized = mimeType?.toLowerCase().trim() ?? "";
|
||||
if (allowedMimeTypes.has(normalized)) {
|
||||
@@ -282,7 +333,7 @@ export const buildServer = async () => {
|
||||
service: "api"
|
||||
}));
|
||||
|
||||
app.get("/api/admin/bootstrap", async () => store.read());
|
||||
app.get("/api/admin/bootstrap", async () => createAdminBootstrapPayload(await store.read()));
|
||||
app.get("/api/admin/live", async () => {
|
||||
const state = await store.read();
|
||||
const pendingCount = state.photoAssets.filter((asset) => {
|
||||
@@ -296,7 +347,9 @@ export const buildServer = async () => {
|
||||
return {
|
||||
cues: state.cues,
|
||||
pendingCount,
|
||||
approvedCount: state.photoAssets.filter((asset) => asset.moderationStatus === "approved").length
|
||||
approvedCount: state.photoAssets.filter((asset) => asset.moderationStatus === "approved").length,
|
||||
libraryRevision: getLibraryRevision(state),
|
||||
programRevision: getProgramRevision(state)
|
||||
};
|
||||
});
|
||||
app.get("/api/admin/library", async () => {
|
||||
@@ -304,7 +357,8 @@ export const buildServer = async () => {
|
||||
return {
|
||||
photoAssets: state.photoAssets,
|
||||
submissions: state.submissions,
|
||||
collections: state.collections
|
||||
collections: state.collections,
|
||||
revision: getLibraryRevision(state)
|
||||
};
|
||||
});
|
||||
|
||||
@@ -315,7 +369,7 @@ export const buildServer = async () => {
|
||||
app.get("/api/assets", async () => (await store.read()).photoAssets);
|
||||
app.get("/api/submissions", async () => (await store.read()).submissions);
|
||||
app.get("/api/show-config", async () => (await store.read()).showConfig);
|
||||
app.post("/api/library/rescan", async () => syncLibrary());
|
||||
app.post("/api/library/rescan", async () => createAdminBootstrapPayload(await syncLibrary()));
|
||||
|
||||
app.put<{ Params: { submissionId: string }; Body: SubmissionUpdatePayload }>(
|
||||
"/api/submissions/:submissionId",
|
||||
|
||||
Reference in New Issue
Block a user