feat: add SSE stream endpoint with GitHub webhook and polling fallback (#237)#299
feat: add SSE stream endpoint with GitHub webhook and polling fallback (#237)#299devendra-w wants to merge 4 commits into
Conversation
|
@devendra-w is attempting to deploy a commit to the PRIYANSHU DOSHI's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
This PR conflicts with recently merged changes. Please rebase onto main: Resolve any conflicts, push, and I'll review. |
|
Hi @devendra-w — this PR has a merge conflict with git fetch upstream
git rebase upstream/main
# resolve conflicts, then:
git push --force-with-leaseOnce rebased, we'll review and merge. |
fc024d6 to
ce2122e
Compare
|
Rebased on main and resolved the merge conflict. Ready for merge @Priyanshu-byte-coder ! |
Priyanshu-byte-coder
left a comment
There was a problem hiding this comment.
Good concept, but several blocking issues:
1. In-memory SSE map doesn't work in serverless
sseConnections is a module-level Map in lib/sse.ts. Vercel deploys Next.js as serverless functions — each request may hit a different cold instance with its own empty map. When a webhook arrives, it writes to its instance's map; the SSE stream is open on a different instance's map. Events never reach the client. This requires a shared pub/sub layer (e.g., Redis pub/sub, or Vercel KV).
2. Missing auth on the SSE endpoint
GET /api/stream?userId=... has no session check. Anyone can subscribe to any user's SSE stream if they know the userId. Add getServerSession and verify the session's githubId matches the requested userId.
3. Duplicate code in stream/route.ts
The entire GET handler is pasted twice in the file. The second copy must be removed.
4. Removes CIAnalytics and Settings link from dashboard
dashboard/page.tsx removes <CIAnalytics /> and the Settings link. These are unrelated to SSE — revert those changes and keep only the <SSEListener> addition.
5. Wrong session field for userId
session?.user?.email ?? session?.user?.name ?? "" — the project uses session.githubId (not user.name). Use session?.githubId ?? "".
The webhook handling concept and SSE fallback-to-polling pattern are solid. Fix these and it's a useful feature.
Priyanshu-byte-coder
left a comment
There was a problem hiding this comment.
Issues found in this PR:
- Missing EOF newline — add a trailing newline to all modified files.
|
Hey @Priyanshu-byte-coder all changes made as requested ready for re-review and merge! |
Priyanshu-byte-coder
left a comment
There was a problem hiding this comment.
PR is conflicting with main. Please rebase:
git fetch upstream
git rebase upstream/main
git push --force-with-lease
39b2dc4 to
5e4580c
Compare
|
Hi @Priyanshu-byte-coder , the TypeScript errors in src/app/api/metrics/contributions/route.ts and src/app/api/metrics/issues/route.ts are pre-existing issues on the main branch confirmed by git diff upstream/main showing zero changes to these files in this PR. These errors exist on main independently of my changes. |
|
Hey @Priyanshu-byte-coder, Addressed all review comments added auth to SSE endpoint, fixed userId to use session.githubId, removed duplicate handler, kept CIAnalytics intact. Pre-existing TypeScript errors in contributions/route.ts are base branch issues unrelated to this PR. Ready to merge! |
|
This PR has merge conflicts with |
|
Hi @Priyanshu-byte-coder! The merge conflicts have been resolved in a clean rebase. I've opened a new PR #998 that is cleanly based on the latest main with no merge commits. Closing this one in favor of the new PR. |
Summary
Dashboard metrics are currently fetched once on load and go stale for active users. This PR adds a Server-Sent Events (SSE) endpoint so the server can push real-time updates when new commits are detected via GitHub webhooks. Falls back to 60s polling if SSE fails.
Closes #237
Type of Change
Changes Made
src/lib/sse.ts— shared in-memory Map to store active SSE connections per usersrc/app/api/stream/route.ts— SSE endpoint atGET /api/stream?userId=src/app/api/webhooks/github/route.ts— GitHub webhook receiver atPOST /api/webhooks/githubwith HMAC-SHA256 signature verification usingcrypto.timingSafeEqualsrc/components/SSEListener.tsx— client component that subscribes to SSE and refreshes dashboard on events, with 60s polling fallback if SSE failssrc/app/dashboard/page.tsx— addedSSEListenercomponent.env.example— addedGITHUB_WEBHOOK_SECRETHow to Test
npm run devstream/dashboard— you should see an activestreamSSE connectionngrokto expose localhost, register the webhook URL on GitHub, and push a commitScreenshots (if UI change)
N/A - Infrastructure change
Checklist
npm run lintpasses locally