perf : better concurrent handle
This commit is contained in:
+44
-14
@@ -33,6 +33,28 @@ import type { PosterBlendMode } from "@/components/public/material-poster";
|
||||
const catalogVersionSchema = z.object({ version: z.string() });
|
||||
const posterBlendModes = new Set(["normal", "multiply", "screen", "overlay", "darken", "lighten", "color-dodge", "color-burn", "hard-light", "soft-light", "difference", "exclusion", "hue", "saturation", "color", "luminosity"]);
|
||||
|
||||
// Leave most of the per-pod pool available to other visitors during cache misses.
|
||||
const PUBLIC_QUERY_CONCURRENCY = 3;
|
||||
|
||||
async function runWithConcurrency<
|
||||
const T extends ReadonlyArray<() => Promise<unknown>>,
|
||||
>(
|
||||
tasks: T,
|
||||
concurrency = PUBLIC_QUERY_CONCURRENCY,
|
||||
): Promise<{ [K in keyof T]: Awaited<ReturnType<T[K]>> }> {
|
||||
const results = new Array<unknown>(tasks.length);
|
||||
let next = 0;
|
||||
await Promise.all(
|
||||
Array.from({ length: Math.min(concurrency, tasks.length) }, async () => {
|
||||
while (next < tasks.length) {
|
||||
const index = next++;
|
||||
results[index] = await tasks[index]();
|
||||
}
|
||||
}),
|
||||
);
|
||||
return results as { [K in keyof T]: Awaited<ReturnType<T[K]>> };
|
||||
}
|
||||
|
||||
function catalogCharacterWithUrls(
|
||||
item: typeof catalogCharacters.$inferSelect,
|
||||
materialByKey = new Map<string, typeof catalogMaterials.$inferSelect>(),
|
||||
@@ -221,7 +243,11 @@ export async function listPublicGuideCards() {
|
||||
.from(guides)
|
||||
.innerJoin(media, eq(media.id, guides.coverMediaId))
|
||||
.where(and(eq(guides.isPublic, true), isNull(guides.trashedAt)))
|
||||
.orderBy(desc(guides.sortOrder), desc(guides.createdAt), asc(guides.name)), getDb().select().from(glossaryAliases)]);
|
||||
.orderBy(desc(guides.sortOrder), desc(guides.createdAt), asc(guides.name)), getDb().select({
|
||||
kind: glossaryAliases.kind,
|
||||
catalogKey: glossaryAliases.catalogKey,
|
||||
alias: glossaryAliases.alias,
|
||||
}).from(glossaryAliases)]);
|
||||
const grouped = aliasesByItem(aliases);
|
||||
return rows.map(({ coverObjectKey, ...guide }) => ({
|
||||
...guide,
|
||||
@@ -303,22 +329,26 @@ async function getGuideContent(slug: string, publicOnly: boolean) {
|
||||
const materialKeys = [...new Set(
|
||||
[...row.character.ascension, ...row.character.leveling].flatMap((group) => group.items.map((item) => item.key)),
|
||||
)];
|
||||
const [sections, weaponConditionsRows, groups, profile, constellationGroups, teamConditionRows, teams, aliases, materials, poster, bleeding] = await Promise.all([
|
||||
getDb().select().from(guideSections).where(and(eq(guideSections.guideId, row.guide.id), eq(guideSections.enabled, true))).orderBy(asc(guideSections.sortOrder)),
|
||||
getDb().select().from(weaponConditions).where(eq(weaponConditions.guideId, row.guide.id)).orderBy(asc(weaponConditions.sortOrder)),
|
||||
getDb().select().from(artifactGroups).where(eq(artifactGroups.guideId, row.guide.id)).orderBy(asc(artifactGroups.sortOrder)),
|
||||
getDb().select().from(artifactProfiles).where(eq(artifactProfiles.guideId, row.guide.id)).limit(1),
|
||||
getDb().select().from(constellationConditions).where(eq(constellationConditions.guideId, row.guide.id)).orderBy(asc(constellationConditions.sortOrder)),
|
||||
getDb().select().from(teamConditions).where(eq(teamConditions.guideId, row.guide.id)).orderBy(asc(teamConditions.sortOrder)),
|
||||
getDb().select().from(teamCompositions).where(eq(teamCompositions.guideId, row.guide.id)).orderBy(asc(teamCompositions.sortOrder)),
|
||||
getDb().select().from(glossaryAliases),
|
||||
materialKeys.length
|
||||
const [sections, weaponConditionsRows, groups, profile, constellationGroups, teamConditionRows, teams, aliases, materials, poster, bleeding] = await runWithConcurrency([
|
||||
() => getDb().select().from(guideSections).where(and(eq(guideSections.guideId, row.guide.id), eq(guideSections.enabled, true))).orderBy(asc(guideSections.sortOrder)),
|
||||
() => getDb().select().from(weaponConditions).where(eq(weaponConditions.guideId, row.guide.id)).orderBy(asc(weaponConditions.sortOrder)),
|
||||
() => getDb().select().from(artifactGroups).where(eq(artifactGroups.guideId, row.guide.id)).orderBy(asc(artifactGroups.sortOrder)),
|
||||
() => getDb().select().from(artifactProfiles).where(eq(artifactProfiles.guideId, row.guide.id)).limit(1),
|
||||
() => getDb().select().from(constellationConditions).where(eq(constellationConditions.guideId, row.guide.id)).orderBy(asc(constellationConditions.sortOrder)),
|
||||
() => getDb().select().from(teamConditions).where(eq(teamConditions.guideId, row.guide.id)).orderBy(asc(teamConditions.sortOrder)),
|
||||
() => getDb().select().from(teamCompositions).where(eq(teamCompositions.guideId, row.guide.id)).orderBy(asc(teamCompositions.sortOrder)),
|
||||
() => getDb().select({
|
||||
kind: glossaryAliases.kind,
|
||||
catalogKey: glossaryAliases.catalogKey,
|
||||
alias: glossaryAliases.alias,
|
||||
}).from(glossaryAliases),
|
||||
() => materialKeys.length
|
||||
? getDb().select().from(catalogMaterials).where(inArray(catalogMaterials.key, materialKeys))
|
||||
: [],
|
||||
row.guide.posterArtMediaId
|
||||
: Promise.resolve([]),
|
||||
() => row.guide.posterArtMediaId
|
||||
? getDb().select().from(media).where(eq(media.id, row.guide.posterArtMediaId)).limit(1)
|
||||
: Promise.resolve([]),
|
||||
getDb().select({ layer: guidePosterBleeding, asset: media }).from(guidePosterBleeding).leftJoin(media, eq(media.id, guidePosterBleeding.mediaId)).where(eq(guidePosterBleeding.guideId, row.guide.id)).orderBy(asc(guidePosterBleeding.sortOrder)),
|
||||
() => getDb().select({ layer: guidePosterBleeding, asset: media }).from(guidePosterBleeding).leftJoin(media, eq(media.id, guidePosterBleeding.mediaId)).where(eq(guidePosterBleeding.guideId, row.guide.id)).orderBy(asc(guidePosterBleeding.sortOrder)),
|
||||
]);
|
||||
const groupedAliases = aliasesByItem(aliases);
|
||||
const materialByKey = new Map(materials.map((item) => [item.key, item]));
|
||||
|
||||
Reference in New Issue
Block a user