pull/14387/head
Aiden Cline 2026-02-20 01:17:08 -06:00
parent d2898141be
commit cfe2d30a26
1 changed files with 14 additions and 18 deletions

View File

@ -197,12 +197,14 @@ export async function aggregateSessionStats(days?: number, projectFilter?: strin
const sessionIds = batch.map((s) => s.id)
// Bulk fetch messages for this batch of sessions
const messageRows = Database.use((db) => db.select().from(MessageTable).where(inArray(MessageTable.session_id, sessionIds)).all())
const messageRows = Database.use((db) =>
db.select().from(MessageTable).where(inArray(MessageTable.session_id, sessionIds)).all(),
)
// Group messages by session_id
const messagesBySession = new Map<string, typeof messageRows>()
const messageIds = messageRows.map((r) => r.id)
for (const row of messageRows) {
const msgs = messagesBySession.get(row.session_id) || []
msgs.push(row)
@ -210,13 +212,15 @@ export async function aggregateSessionStats(days?: number, projectFilter?: strin
}
// Bulk fetch parts for all these messages
let partRows: typeof PartTable.$inferSelect[] = []
let partRows: (typeof PartTable.$inferSelect)[] = []
if (messageIds.length > 0) {
// Chunk message IDs if there are too many for a single IN clause (SQLite has limits)
const PART_BATCH_SIZE = 500
for (let j = 0; j < messageIds.length; j += PART_BATCH_SIZE) {
const idBatch = messageIds.slice(j, j + PART_BATCH_SIZE)
const parts = Database.use((db) => db.select().from(PartTable).where(inArray(PartTable.message_id, idBatch)).all())
const parts = Database.use((db) =>
db.select().from(PartTable).where(inArray(PartTable.message_id, idBatch)).all(),
)
partRows.push(...parts)
}
}
@ -229,18 +233,12 @@ export async function aggregateSessionStats(days?: number, projectFilter?: strin
partsByMessage.set(row.message_id, parts)
}
for (const session of batch) {
const batchResults = batch.map((session) => {
const rawMessages = messagesBySession.get(session.id) || []
// Construct the MessageV2 objects locally instead of doing another N queries
const messages = rawMessages.map(
(row) =>
({
id: row.id,
sessionID: row.session_id,
info: row.data,
parts: partsByMessage.get(row.id) || [],
}) as MessageV2.WithParts,
)
const messages = rawMessages.map((row) => ({
info: { ...row.data, id: row.id, sessionID: row.session_id } as MessageV2.Info,
parts: partsByMessage.get(row.id) || [],
}))
let sessionCost = 0
let sessionTokens = { input: 0, output: 0, reasoning: 0, cache: { read: 0, write: 0 } }
@ -328,8 +326,6 @@ export async function aggregateSessionStats(days?: number, projectFilter?: strin
}
})
const batchResults = await Promise.all(batchPromises)
for (const result of batchResults) {
earliestTime = Math.min(earliestTime, result.earliestTime)
latestTime = Math.max(latestTime, result.latestTime)