You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Background .env.example documents NEXT_PUBLIC_ACTIVITY_REFRESH_MS as an "Activity delivery fallback interval," describing automatic SSE with a polling fallback, and notes that setting it to 0 "disable[s] automatic SSE and polling while retaining manual refresh." This confirms the /activity page relies on a live SSE connection with polling as a secondary mechanism.
Problem
There's no documented or apparent handling for what happens when the SSE connection drops (network blip, server restart, proxy timeout): does the client silently stop receiving updates until a manual refresh, does it retry immediately in a tight loop, and are events that occurred during the disconnect window lost entirely? None of this is addressed by the simple polling-interval fallback alone.
Expected outcome
The activity feed client detects SSE disconnects, retries the connection using exponential backoff with jitter (capped at a sane maximum), and on reconnect, requests any activity events that occurred after the last event it successfully received (using a timestamp or event-id cursor) so no events are silently lost during a disconnect window shorter than the outage-recovery threshold.
Suggested implementation
Add a lastEventId/lastSeenTimestamp cursor tracked client-side (and ideally acknowledged server-side via SSE's native Last-Event-ID support).
Implement exponential backoff (e.g. 1s → 2s → 4s ... capped at 30s) with jitter for reconnect attempts.
On successful reconnect, call the existing paginated activity API (see Issue Add wallet address validation to the /verify command #1, if implemented) with an after=<cursor> parameter to backfill missed events before resuming the live stream.
Ensure the existing polling fallback interval still functions independently as the last line of defense if SSE is fully disabled (NEXT_PUBLIC_ACTIVITY_REFRESH_MS=0 should still allow manual refresh only, unchanged).
Acceptance criteria
Simulating an SSE disconnect (e.g. by having the mock endpoint close the connection) triggers a backoff-based reconnect rather than a tight retry loop or silent failure.
Events generated during a simulated disconnect window are backfilled once the client reconnects.
Existing polling-fallback behavior (NEXT_PUBLIC_ACTIVITY_REFRESH_MS) is unaffected for environments where SSE is disabled.
Reconnect attempts and backfill requests are covered by tests (using fake timers where appropriate).
pnpm --filter @guildpass/dashboard test and pnpm typecheck pass.
Difficulty: Advanced
Type: Performance
Background
.env.exampledocumentsNEXT_PUBLIC_ACTIVITY_REFRESH_MSas an "Activity delivery fallback interval," describing automatic SSE with a polling fallback, and notes that setting it to0"disable[s] automatic SSE and polling while retaining manual refresh." This confirms the/activitypage relies on a live SSE connection with polling as a secondary mechanism.Problem
There's no documented or apparent handling for what happens when the SSE connection drops (network blip, server restart, proxy timeout): does the client silently stop receiving updates until a manual refresh, does it retry immediately in a tight loop, and are events that occurred during the disconnect window lost entirely? None of this is addressed by the simple polling-interval fallback alone.
Expected outcome
The activity feed client detects SSE disconnects, retries the connection using exponential backoff with jitter (capped at a sane maximum), and on reconnect, requests any activity events that occurred after the last event it successfully received (using a timestamp or event-id cursor) so no events are silently lost during a disconnect window shorter than the outage-recovery threshold.
Suggested implementation
lastEventId/lastSeenTimestampcursor tracked client-side (and ideally acknowledged server-side via SSE's nativeLast-Event-IDsupport)./verifycommand #1, if implemented) with anafter=<cursor>parameter to backfill missed events before resuming the live stream.NEXT_PUBLIC_ACTIVITY_REFRESH_MS=0should still allow manual refresh only, unchanged).Acceptance criteria
NEXT_PUBLIC_ACTIVITY_REFRESH_MS) is unaffected for environments where SSE is disabled.pnpm --filter @guildpass/dashboard testandpnpm typecheckpass.Likely affected files/directories
apps/dashboard/app/activity/, activity SSE route/handler (apps/dashboard/app/api/activity/**or equivalent), client-side activity feed hook/component.