opt(tierlist): parallelize ssr queries

This commit is contained in:
2026-04-09 17:02:29 +07:00 Unverified
parent 37b31c782c
commit e376dd77bf
8 changed files with 79 additions and 48 deletions
+1 -1
View File
@@ -4,9 +4,9 @@ import Link from "next/link";
import { useMemo, useState } from "react";
import Avatar from "@/components/avatar";
import SearchBox, { type Filters, type ParsedQuery } from "@/components/search";
import { SimpleTooltip } from "@/components/tooltip";
import { Button } from "@/components/ui/button";
import { type characters, element } from "@/lib/db/schema";
import { SimpleTooltip } from "@/components/tooltip";
/** Filters and their value providers */
const filters: Filters = {
+1 -1
View File
@@ -24,6 +24,7 @@ import {
CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Kbd } from "@/components/ui/kbd";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { Tooltip, TooltipContent } from "@/components/ui/tooltip";
@@ -34,7 +35,6 @@ import { CharacterChooser, ClearCookie, Disclaimer } from "./client";
import { ArtifactFormWrapper } from "./form";
import { LiveButton } from "./live";
import { RulesDialog } from "./rules";
import { Kbd } from "@/components/ui/kbd";
export const metadata: Metadata = {
title: "เสือกไอดีชาวบ้าน",
+1 -1
View File
@@ -3,9 +3,9 @@ import Link from "next/link";
import type { ReactNode } from "react";
import Banner from "#/banner_t.webp";
import ArtifactLogo from "#/logos/artifact.webp";
import GuideLogo from "#/logos/guide.webp";
import RubgramLogo from "#/logos/rubgram.webp";
import TierlistLogo from "#/logos/tierlist.webp";
import GuideLogo from "#/logos/guide.webp";
import Image from "@/components/image";
import { SimpleTooltip } from "@/components/tooltip";
import { cn } from "@/lib/utils";
+1 -1
View File
@@ -36,9 +36,9 @@ import {
TooltipTrigger,
} from "@/components/ui/tooltip";
import { shared } from "@/lib/comms";
import { sse } from "@/lib/db/sse-endpoints";
import { cn } from "@/lib/utils";
import { setFree, setLimit, toggleCheck, toggleLock } from "../api";
import { sse } from "@/lib/db/sse-endpoints";
export function SidebarLink({
submission,
+14 -15
View File
@@ -84,21 +84,20 @@ export default async function TierlistPage({
: ([] as (typeof characters.$inferSelect)[]);
// fetch rows, columns, badges data...
const tiers = await tx
.select()
.from(tierlistTiers)
.orderBy(tierlistTiers.order);
const columns = await tx
.select()
.from(tierlistColumns)
.orderBy(tierlistColumns.order);
const badgesList = await tx
.select()
.from(tierlistBadges)
.orderBy(tierlistBadges.order)
.where(
or(isNull(tierlistBadges.type), eq(tierlistBadges.type, version.type)),
);
const [tiers, columns, badgesList] = await Promise.all([
tx.select().from(tierlistTiers).orderBy(tierlistTiers.order),
tx.select().from(tierlistColumns).orderBy(tierlistColumns.order),
tx
.select()
.from(tierlistBadges)
.orderBy(tierlistBadges.order)
.where(
or(
isNull(tierlistBadges.type),
eq(tierlistBadges.type, version.type),
),
),
]);
const badges = badgesList.map((b) => ({
...b,
tier: tiers.filter((t) => t.badges?.includes(b.id)).map((t) => t.id),
+3 -3
View File
@@ -15,11 +15,11 @@ import {
CopyPlus,
FileQuestionMark,
Home,
TriangleAlert,
Pencil,
Settings,
Settings2,
Trash2,
TriangleAlert,
X,
} from "lucide-react";
import Link from "next/link";
@@ -64,6 +64,7 @@ import {
TooltipTrigger,
} from "@/components/ui/tooltip";
import { tlPlacements, tlState } from "@/lib/api";
import { authClient } from "@/lib/auth-client";
import { shared } from "@/lib/comms";
import type {
characters,
@@ -74,12 +75,11 @@ import type {
tierlistTypes,
tierlistVersions,
} from "@/lib/db/schema";
import { authClient } from "@/lib/auth-client";
import { tlSse } from "@/lib/db/sse-endpoints";
import { cn } from "@/lib/utils";
import { TierListCell } from "./cell";
import { Draggable } from "./character";
import { TierListContext } from "./context";
import { tlSse } from "@/lib/db/sse-endpoints";
function Untiered({
children,
+28 -13
View File
@@ -1,10 +1,10 @@
import { desc, eq, not } from "drizzle-orm";
import { and, eq, getTableColumns, not, sql } from "drizzle-orm";
import { ArrowLeft } from "lucide-react";
import type { Metadata } from "next";
import Link from "next/link";
import Image from "@/components/image";
import { db } from "@/lib/db";
import { tierlistTypes, tierlistVersions } from "@/lib/db/schema";
import { ArrowLeft } from "lucide-react";
export const metadata: Metadata = {
title: "จัดเทียร์ลิสต์",
@@ -17,19 +17,34 @@ export default async function TierlistSelectionPage({
params: Promise<{ type: string }>;
}) {
const { type: typeId } = await params;
const types = await db
.select()
const vers = await db
.select({
...getTableColumns(tierlistTypes),
versions: sql<(typeof tierlistVersions.$inferSelect)[]>`
COALESCE(
json_agg(
json_build_object(
'id', ${tierlistVersions.id},
'name', ${tierlistVersions.name},
'image', ${tierlistVersions.image}
) ORDER BY ${tierlistVersions.order} DESC)
FILTER (WHERE ${tierlistVersions.id} IS NOT NULL),
'[]'
)
`.as("versions"),
})
.from(tierlistTypes)
.leftJoin(
tierlistVersions,
and(
eq(tierlistVersions.type, tierlistTypes.id),
not(tierlistVersions.hidden),
),
)
.groupBy(tierlistTypes.id)
.orderBy(tierlistTypes.id)
.where(eq(tierlistTypes.id, typeId));
const versionsList = await db
.select()
.from(tierlistVersions)
.orderBy(desc(tierlistVersions.order))
.where(not(tierlistVersions.hidden));
const vers = types.map((t) => ({
...t,
versions: versionsList.filter((v) => v.type === t.id),
}));
return (
<div className="max-w-7xl min-h-full flex flex-col gap-6 mx-auto py-8 px-4">
{vers.map((t) => (
+30 -13
View File
@@ -1,14 +1,14 @@
import { desc, not } from "drizzle-orm";
import { and, eq, getTableColumns, not, sql } from "drizzle-orm";
import { ArrowRight } from "lucide-react";
import type { Metadata } from "next";
import Link from "next/link";
import TierlistLogo from "#/logos/tierlist.webp";
import { HorizontalDiv } from "@/components/horizontal";
import { SimpleTooltip } from "@/components/tooltip";
import Image from "@/components/image";
import { SimpleTooltip } from "@/components/tooltip";
import { ScrollBar } from "@/components/ui/scroll-area";
import { db } from "@/lib/db";
import { tierlistTypes, tierlistVersions } from "@/lib/db/schema";
import { ArrowRight } from "lucide-react";
export const metadata: Metadata = {
title: "จัดเทียร์ลิสต์",
@@ -16,16 +16,33 @@ export const metadata: Metadata = {
};
export default async function TierlistSelectionPage() {
const types = await db.select().from(tierlistTypes).orderBy(tierlistTypes.id);
const versionsList = await db
.select()
.from(tierlistVersions)
.orderBy(desc(tierlistVersions.order))
.where(not(tierlistVersions.hidden));
const vers = types.map((t) => ({
...t,
versions: versionsList.filter((v) => v.type === t.id),
}));
const vers = await db
.select({
...getTableColumns(tierlistTypes),
versions: sql<(typeof tierlistVersions.$inferSelect)[]>`
COALESCE(
json_agg(
json_build_object(
'id', ${tierlistVersions.id},
'name', ${tierlistVersions.name},
'image', ${tierlistVersions.image}
) ORDER BY ${tierlistVersions.order} DESC)
FILTER (WHERE ${tierlistVersions.id} IS NOT NULL),
'[]'
)
`.as("versions"),
})
.from(tierlistTypes)
.leftJoin(
tierlistVersions,
and(
eq(tierlistVersions.type, tierlistTypes.id),
not(tierlistVersions.hidden),
),
)
.groupBy(tierlistTypes.id)
.orderBy(tierlistTypes.id);
return (
<div className="max-w-full min-h-full flex flex-col justify-center gap-2 mx-2">
<center className="mb-2">