Problem Statement
DevTrack's dashboard uses Server-Sent Events (SSE) to push live updates (such as goal completions or recent commit counts) directly to users without constant HTTP polling.
Currently, this system has two critical architectural defects that prevent real-time updates from functioning:
- Dangling Connection Map: The active connection route
/api/stream/route.ts manages connection caps using activeStreamConnections, but never registers the connection controller in the sseConnections registry defined in src/lib/sse.ts. As a result, the registry remains empty, and the server-side dispatcher has no stream references to push events to.
- Key/Username Mismatch: The GitHub webhook route invokes push notifications using
sendSSEEvent(githubLogin, "commit", ...), passing the raw GitHub username string. However, the stream handler /api/stream/route.ts sets up connection contexts using the database UUID (user.id). Even if the connections were registered, the lookup key mismatch (githubLogin vs userId UUID) would prevent the message from reaching the socket.
Consequently, active dashboards never receive instant updates and must rely entirely on the 60-second database polling fallback.
Proposed Solution
Align the connection registry keys and register controllers in the active stream handler:
- Connection Registration: Update the
ReadableStream hooks in src/app/api/stream/route.ts to insert and remove the stream controllers:
- In the stream's
start(controller) hook:
sseConnections.set(userId, controller);
- In the
closeStream() cleanup method:
sseConnections.delete(userId);
- Resolve User UUID on Webhook: Update
src/app/api/webhooks/github/route.ts to look up the database UUID associated with the incoming push webhook's githubLogin:
- Query the
users table to fetch the matching id (database UUID).
- Use the resolved UUID instead of
githubLogin when calling sendSSEEvent:
const { data: dbUser } = await supabaseAdmin
.from("users")
.select("id")
.eq("github_login", githubLogin)
.single();
if (dbUser?.id) {
sendSSEEvent(dbUser.id, "commit", {
repo: payload.repository?.full_name,
timestamp: new Date().toISOString(),
});
}
Feature Area
New Feature Area
Alternatives Considered
- Keying SSE connections by
githubLogin: We considered keying the sseConnections registry by GitHub usernames instead of database UUIDs. However, GitHub logins are mutable (users can change their username), whereas database UUIDs remain static and secure. Keying by database UUID is standard and guards against account mutation bugs.
Acceptance Criteria
- The
sseConnections Map successfully registers the active stream controller when a client establishes a connection to /api/stream.
- Disconnecting or closing a tab successfully removes the controller from
sseConnections to prevent memory leaks.
- The GitHub push webhook route queries the database to map the commit author's username to their database UUID.
- Active client dashboards receive commit events instantly upon pushing code to GitHub, bypassing the 60-second fallback database polling interval.
- Unit tests verify connection registration, payload routing via database UUIDs, and proper cleanup on socket close.
Additional Context
No response
Problem Statement
DevTrack's dashboard uses Server-Sent Events (SSE) to push live updates (such as goal completions or recent commit counts) directly to users without constant HTTP polling.
Currently, this system has two critical architectural defects that prevent real-time updates from functioning:
/api/stream/route.tsmanages connection caps usingactiveStreamConnections, but never registers the connection controller in thesseConnectionsregistry defined insrc/lib/sse.ts. As a result, the registry remains empty, and the server-side dispatcher has no stream references to push events to.sendSSEEvent(githubLogin, "commit", ...), passing the raw GitHub username string. However, the stream handler/api/stream/route.tssets up connection contexts using the database UUID (user.id). Even if the connections were registered, the lookup key mismatch (githubLoginvsuserIdUUID) would prevent the message from reaching the socket.Consequently, active dashboards never receive instant updates and must rely entirely on the 60-second database polling fallback.
Proposed Solution
Align the connection registry keys and register controllers in the active stream handler:
ReadableStreamhooks insrc/app/api/stream/route.tsto insert and remove the stream controllers:start(controller)hook:closeStream()cleanup method:src/app/api/webhooks/github/route.tsto look up the database UUID associated with the incoming push webhook'sgithubLogin:userstable to fetch the matchingid(database UUID).githubLoginwhen callingsendSSEEvent:Feature Area
New Feature Area
Alternatives Considered
githubLogin: We considered keying thesseConnectionsregistry by GitHub usernames instead of database UUIDs. However, GitHub logins are mutable (users can change their username), whereas database UUIDs remain static and secure. Keying by database UUID is standard and guards against account mutation bugs.Acceptance Criteria
sseConnectionsMap successfully registers the active stream controller when a client establishes a connection to/api/stream.sseConnectionsto prevent memory leaks.Additional Context
No response