perf : better concurrent handle
CI / Verify (push) Successful in 1m29s
CI / Build immutable images and deploy (push) Successful in 1m48s

This commit is contained in:
2026-09-10 19:08:25 +07:00 Unverified
parent 00f59e6e85
commit 89be58c517
7 changed files with 59 additions and 19 deletions
+2 -2
View File
@@ -198,8 +198,8 @@ Kustomize resources live in `k8s/` and define:
- ClusterIP port 3000 and Traefik ingress for `guide.sudloh.com`.
- Cloudflare edge TLS with the cluster's standard HTTP Traefik origin route.
- Startup, liveness, and dependency-aware readiness probes.
- Web requests of 500m CPU/512 MiB and limits of 1 CPU/1 GiB.
- HPA from 2 to 6 web replicas at 70% CPU and a PDB with one available.
- Web requests of 500m CPU/1 GiB and limits of 1 CPU/2 GiB.
- HPA from 2 to 6 web replicas at 70% CPU or 75% memory and a PDB with one available.
- Non-root, read-only containers with dropped capabilities and seccomp.
- ARM64 scheduling constraints matching the production hosts and images.
- A versioned migration Job and namespace-scoped CI deployer permissions.
@@ -62,6 +62,7 @@ export function StructuredDirectory({ guides }: { guides: GuideCard[] }) {
<Link
key={guide.id}
href={`/${guide.slug}`}
prefetch={false}
className="group rounded-xl outline-none focus-visible:ring-2 focus-visible:ring-ring"
>
<Card className="h-full overflow-hidden py-0 transition-transform group-hover:-translate-y-0.5">
+2 -2
View File
@@ -57,10 +57,10 @@ spec:
resources:
requests:
cpu: 500m
memory: 512Mi
memory: 1Gi
limits:
cpu: "1"
memory: 1Gi
memory: 2Gi
startupProbe:
httpGet:
path: /api/health
+6
View File
@@ -23,3 +23,9 @@ spec:
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 75
+44 -14
View File
@@ -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]));
+3 -1
View File
@@ -17,7 +17,7 @@ describe("production deployment contract", () => {
expect(deployment).toContain("path: /api/health");
expect(deployment).toContain("kubernetes.io/arch: arm64");
expect(deployment).toMatch(
/requests:\s+cpu: 500m\s+memory: 512Mi\s+limits:\s+cpu: "1"\s+memory: 1Gi/u,
/requests:\s+cpu: 500m\s+memory: 1Gi\s+limits:\s+cpu: "1"\s+memory: 2Gi/u,
);
expect(deployment).toContain("runAsNonRoot: true");
expect(deployment).toContain("runAsUser: 1000");
@@ -53,6 +53,8 @@ describe("production deployment contract", () => {
expect(hpa).toContain("minReplicas: 2");
expect(hpa).toContain("maxReplicas: 6");
expect(hpa).toContain("averageUtilization: 70");
expect(hpa).toContain("name: memory");
expect(hpa).toContain("averageUtilization: 75");
expect(pdb).toContain("minAvailable: 1");
});
+1
View File
@@ -38,6 +38,7 @@ describe("public rendering performance", () => {
'fetchPriority={index === 0 ? "high" : undefined}',
);
expect(directory).not.toContain("preload={index === 0}");
expect(directory).toContain("prefetch={false}");
});
it("publishes a public-only crawler policy", () => {