perf: optimize CMS queries, caching, and asset delivery
Database: - Add missing indexes (users.credits, users_currency(type,amount), users_settings.respects_received, camera_web.timestamp, messenger_offline.user_id) via migrations 0020/0021 - Use partial .select() everywhere instead of SELECT * (tickets, users, rooms, audit logs, catalog tree, polls, radio, password reset) - Add queryPrepared/queryPreparedOne (server-side prepared statements) and switch the login check to a prepared statement; drop dead cache options from the pool config - Raise total_users/total_rooms COUNT(*) cache TTL to 5m Caching: - Consolidate the three cache helpers (cached, redisCache, cachedQuery) into a single memory-first implementation backed by Redis - invalidateKey now clears the in-process cache as well as Redis - Cache homepage sections, news list, and leaderboard tabs; share one news_list cache key between homepage and news archive - siteSettings: in-process cache with TTL so repeated getters no longer pay a Redis round-trip per call - Share a 10s poll cache across all radio SSE connections - Normalize timestamps after cache reads (Redis JSON round-trip) Assets: - Enable AVIF/WebP via images.formats and remove unoptimized from news covers and the homepage hero (149KB jpg) with proper sizes/priority - Support ?format=webp|avif|png in the /imaging proxy via sharp Other: - Fix pnpm supply-chain minimumReleaseAge failures by excluding the freshly-published packages (next 16.3.1, hookform resolvers 5.8.0, resend 6.20.0) - Remove unused before/after fields from housekeeping AuditEntry
This commit is contained in:
1 parent
dc9e5a567c
commit
e5ec3c1f06
29 files changed
+532
-322
No files matched your search
@@ -81,8 +81,6 @@ interface AuditEntry {
|
||||
action: string;
|
||||
target: string;
|
||||
targetId: number | null;
|
||||
before: unknown;
|
||||
after: unknown;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,18 @@ export async function loadRoom(id: string) {
|
||||
if (Number.isNaN(roomId)) notFound();
|
||||
|
||||
const [room] = await db
|
||||
.select()
|
||||
.select({
|
||||
id: Rooms.id,
|
||||
ownerId: Rooms.ownerId,
|
||||
ownerName: Rooms.ownerName,
|
||||
name: Rooms.name,
|
||||
description: Rooms.description,
|
||||
state: Rooms.state,
|
||||
users: Rooms.users,
|
||||
usersMax: Rooms.usersMax,
|
||||
category: Rooms.category,
|
||||
score: Rooms.score,
|
||||
})
|
||||
.from(Rooms)
|
||||
.where(eq(Rooms.id, roomId))
|
||||
.limit(1);
|
||||
|
||||
@@ -21,7 +21,24 @@ export async function loadUserById(id: string) {
|
||||
numericId > 0 &&
|
||||
String(numericId) === id;
|
||||
const [user] = await db
|
||||
.select()
|
||||
.select({
|
||||
id: User.id,
|
||||
username: User.username,
|
||||
mail: User.mail,
|
||||
gender: User.gender,
|
||||
machineId: User.machineId,
|
||||
twoFactorConfirmedAt: User.twoFactorConfirmedAt,
|
||||
rank: User.rank,
|
||||
online: User.online,
|
||||
motto: User.motto,
|
||||
look: User.look,
|
||||
credits: User.credits,
|
||||
pixels: User.pixels,
|
||||
accountCreated: User.accountCreated,
|
||||
lastLogin: User.lastLogin,
|
||||
ipRegister: User.ipRegister,
|
||||
ipCurrent: User.ipCurrent,
|
||||
})
|
||||
.from(User)
|
||||
.where(isNumeric ? eq(User.id, numericId) : eq(User.username, id))
|
||||
.limit(1);
|
||||
@@ -40,7 +57,10 @@ export async function loadUserById(id: string) {
|
||||
] = await Promise.all([
|
||||
db.select().from(UsersCurrency).where(eq(UsersCurrency.userId, user.id)),
|
||||
db
|
||||
.select()
|
||||
.select({
|
||||
id: UsersBadges.id,
|
||||
badgeCode: UsersBadges.badgeCode,
|
||||
})
|
||||
.from(UsersBadges)
|
||||
.where(eq(UsersBadges.userId, user.id))
|
||||
.orderBy(asc(UsersBadges.slotId)),
|
||||
|
||||
Reference in new issue
Block a user