[api] fix slow rooms badge query

This commit is contained in:
Devin Zuczek
2026-10-23 22:57:53 -04:00
parent f9600c1836
commit 09e40af6b7
4 changed files with 81 additions and 8 deletions
+21 -7
View File
@@ -2846,17 +2846,31 @@ async function hydrateRooms(db: D1Database, rooms: Room[]): Promise<Room[]> {
return rooms
}
/**
* Whether `custom_avatar_item` has been seen on this database. API owns that table's migration
* and room deployments can precede it, so {@link attachBadges} probes for it — but a table
* never goes away once created, so a hit is remembered and the probe (a scan of
* `sqlite_master`, on every room page) runs only until the first hit.
*/
let badgeTableSeen = false
/** Published room-linked image badges; drafts remain on the creator's Studio shelf. */
async function attachBadges(db: D1Database, rooms: Room[]): Promise<void> {
if (!rooms.length) return
// API owns this table's migration; room deployments can precede that migration.
const exists = await db
.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='custom_avatar_item'")
.first()
if (!exists) {
for (const room of rooms) room.Badges = []
return
if (!badgeTableSeen) {
const exists = await db
.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='custom_avatar_item'")
.first()
if (!exists) {
for (const room of rooms) room.Badges = []
return
}
badgeTableSeen = true
}
// Served by `idx_custom_avatar_item_badge_room` (api migrations/0035), a PARTIAL index over
// `outfit_type = 1000` keyed by the `json_extract(data,'$.CustomBadgeMetadata.RoomId')`
// expression. SQLite matches both only as written: drop or rephrase either term and this
// goes back to scanning every custom avatar item on every room page.
const rows = await db
.prepare(
"SELECT data,json_extract(data,'$.CustomBadgeMetadata.RoomId') AS room_id FROM custom_avatar_item WHERE outfit_type=1000 AND accessibility<>0 AND json_array_length(json_extract(data,'$.CurrentSaves'))>0 AND json_extract(data,'$.CustomBadgeMetadata.RoomId') IN (SELECT value FROM json_each(?))"