Add performance optimizations and component refactors
- Cache read-heavy public API routes via redisCache (leaderboard, values, shop, articles, photos, guilds, teams, staff, users, home, radio, badges) - Add single-flight and bounded-memory cache layer with unit tests - Parallelize independent DB queries on search, rares, shop, staff, polls and profile pages - Push radio points leaderboard aggregation to SQL with a LIMIT - Split studio-client and import-furni-client into focused modules - Clean up next.config.ts
This commit is contained in:
1 parent
54f2bc5e0c
commit
f285a7cd98
42 files changed
+1616
-1205
No files matched your search
@@ -8,6 +8,7 @@
|
||||
import { eq } from "drizzle-orm";
|
||||
import { apiJson } from "@/lib/api";
|
||||
import { db, User } from "@/lib/db";
|
||||
import { apiCacheKey, cacheSafe, redisCache } from "@/lib/redis-cache";
|
||||
|
||||
export async function GET(
|
||||
_req: Request,
|
||||
@@ -16,33 +17,45 @@ export async function GET(
|
||||
const { username } = await params;
|
||||
|
||||
try {
|
||||
const [user] = await db
|
||||
.select({
|
||||
username: User.username,
|
||||
look: User.look,
|
||||
motto: User.motto,
|
||||
rank: User.rank,
|
||||
credits: User.credits,
|
||||
online: User.online,
|
||||
accountCreated: User.accountCreated,
|
||||
})
|
||||
.from(User)
|
||||
.where(eq(User.username, username))
|
||||
.limit(1);
|
||||
const user = await redisCache(
|
||||
apiCacheKey(`users:${username}`),
|
||||
30,
|
||||
async () => {
|
||||
const [row] = await db
|
||||
.select({
|
||||
username: User.username,
|
||||
look: User.look,
|
||||
motto: User.motto,
|
||||
rank: User.rank,
|
||||
credits: User.credits,
|
||||
online: User.online,
|
||||
accountCreated: User.accountCreated,
|
||||
})
|
||||
.from(User)
|
||||
.where(eq(User.username, username))
|
||||
.limit(1);
|
||||
|
||||
if (!row) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return cacheSafe({
|
||||
username: row.username,
|
||||
look: row.look,
|
||||
motto: row.motto,
|
||||
rank: row.rank,
|
||||
credits: row.credits,
|
||||
online: row.online === "1",
|
||||
accountCreated: row.accountCreated,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
if (!user) {
|
||||
return apiJson({ error: "User not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
return apiJson({
|
||||
username: user.username,
|
||||
look: user.look,
|
||||
motto: user.motto,
|
||||
rank: user.rank,
|
||||
credits: user.credits,
|
||||
online: user.online === "1",
|
||||
accountCreated: user.accountCreated,
|
||||
});
|
||||
return apiJson(user);
|
||||
} catch {
|
||||
// DB unreachable — behave as "not found" rather than 500.
|
||||
return apiJson({ error: "User not found" }, { status: 404 });
|
||||
|
||||
Reference in new issue
Block a user