Skip to content

Commit 3c29de2

Browse files
committed
fix(analytics): prevent publicPlatformStats crash with null-safe tokens and 1000 session limit
1 parent c42f7f9 commit 3c29de2

5 files changed

Lines changed: 174 additions & 448 deletions

File tree

changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ Format based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2525

2626
### Fixed
2727

28+
- Fixed publicPlatformStats query causing production crash and black screen
29+
- Added null-safe token handling (s.totalTokens ?? 0) to prevent NaN values
30+
- Limited query to 1000 most recent sessions to avoid timeout on large datasets
31+
- Fixed Login page going black after initial render on opensync.dev
2832
- Fixed homepage blank screen in production caused by auth loading blocking page render
2933
- Changed loading guard to only block during OAuth callback (when URL contains ?code=)
3034
- Anonymous visitors now see homepage content immediately without waiting for Convex auth

convex/analytics.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ export const publicMessageGrowth = query({
657657
date: v.string(),
658658
count: v.number(),
659659
cumulative: v.number(),
660-
})
660+
}),
661661
),
662662
handler: async (ctx) => {
663663
// Group sessions by date and sum their messageCount
@@ -678,7 +678,8 @@ export const publicMessageGrowth = query({
678678
// Sort dates and calculate cumulative
679679
const sortedDates = Object.keys(byDate).sort();
680680
let cumulative = 0;
681-
const result: Array<{ date: string; count: number; cumulative: number }> = [];
681+
const result: Array<{ date: string; count: number; cumulative: number }> =
682+
[];
682683

683684
for (const date of sortedDates) {
684685
cumulative += byDate[date];
@@ -714,8 +715,8 @@ export const publicPlatformStats = query({
714715
),
715716
}),
716717
handler: async (ctx) => {
717-
// Fetch all sessions for platform-wide stats
718-
const sessions = await ctx.db.query("sessions").collect();
718+
// Fetch recent sessions for platform-wide stats (limit to 1000 to avoid timeout)
719+
const sessions = await ctx.db.query("sessions").order("desc").take(1000);
719720

720721
if (sessions.length === 0) {
721722
return {
@@ -732,21 +733,24 @@ export const publicPlatformStats = query({
732733
{};
733734

734735
for (const s of sessions) {
736+
// Safe token value (handle null/undefined)
737+
const tokens = s.totalTokens ?? 0;
738+
735739
// Model aggregation
736740
const model = s.model || "unknown";
737741
if (!modelMap[model]) {
738742
modelMap[model] = { totalTokens: 0, sessions: 0 };
739743
}
740-
modelMap[model].totalTokens += s.totalTokens;
744+
modelMap[model].totalTokens += tokens;
741745
modelMap[model].sessions += 1;
742746

743-
// Source/CLI aggregation (supports: opencode, claude-code, cursor, droid, codex, amp, etc.)
747+
// Source/CLI aggregation (supports: opencode, claude-code, cursor, droid, codex, amp, pi, etc.)
744748
const source = s.source || "opencode";
745749
if (!sourceMap[source]) {
746750
sourceMap[source] = { sessions: 0, totalTokens: 0 };
747751
}
748752
sourceMap[source].sessions += 1;
749-
sourceMap[source].totalTokens += s.totalTokens;
753+
sourceMap[source].totalTokens += tokens;
750754
}
751755

752756
// Sort models by total tokens and take top 5

0 commit comments

Comments
 (0)