-
Notifications
You must be signed in to change notification settings - Fork 56
fix(eventsource): Make EventSource creation in frontend more robust with retry mechanism #1113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Summary of ChangesHello @kalpadhwaryu, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request enhances the stability of frontend EventSource connections by introducing a sophisticated retry mechanism, complete with exponential backoff and connection timeouts. Concurrently, it refines the user experience by standardizing and simplifying error messages presented through toast notifications, making them less technical and more accessible to end-users. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
WalkthroughAdds robust SSE retry and token-refresh flow in useChatStream with exponential backoff, connection timeout, and cleanup of prior EventSource instances. Updates toast messages in agent and API key routes to generic, fixed descriptions. No exported/public signatures changed. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant U as Chat UI
participant H as useChatStream
participant A as Auth Service
participant S as Server (SSE)
rect rgba(230,245,255,0.5)
note over U,H: Start chat stream
U->>H: startStream()
H->>A: getAccessToken()
A-->>H: token
H->>S: create EventSource (with token)
S-->>H: open / message events
H-->>U: deliver stream chunks
end
alt Error on connect / stream
H--xS: close EventSource and cleanup
opt Token refresh path
H->>A: refreshToken()
alt Refresh succeeds
note over H: Exponential backoff (1st, 2nd, ... attempt)
H->>S: re-create EventSource
S-->>H: open / message events
H-->>U: deliver stream chunks
else Refresh fails or max retries
H-->>U: show generic error toast
end
end
else Connection stalls (>5s)
note over H: Timeout triggers refresh-and-retry
H->>A: refreshToken()
H->>S: re-create EventSource (after backoff)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request significantly improves the robustness of EventSource
creation by adding a comprehensive retry mechanism with exponential backoff, connection timeouts, and token refresh handling. This is a great enhancement for the reliability of real-time features. The move to more user-friendly, generic error messages in the UI is also a positive change. My review focuses on further improving debuggability by suggesting more detailed error messages for developers in promise rejections and ensuring that errors are consistently logged to the console, especially where generic UI messages might otherwise hide important diagnostic information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
frontend/src/routes/_authenticated/agent.tsx (2)
1025-1035
: Bug: isGeneratingPrompt remains true when EventSource creation failsEarly return after a failed createAuthEventSource leaves the button disabled/spinner on. Reset state before returning.
try { promptGenerationEventSourceRef.current = await createAuthEventSource( url.toString(), ) } catch (err) { console.error("Failed to create EventSource:", err) toast({ title: "Error", description: "Something went wrong. Please try again.", variant: "destructive", }) - return + setIsGeneratingPrompt(false) + return }
2395-2404
: Bug: isStreaming (and transient state) not reset when EventSource creation failsIf EventSource creation throws, we return without clearing streaming flags, causing the chat to stay “stuck”.
try { eventSourceRef.current = await createAuthEventSource(url.toString()) } catch (err) { console.error("Failed to create EventSource:", err) toast({ title: "Error", description: "Something went wrong. Please try again.", variant: "destructive", }) - return + // Reset transient streaming state + setIsStreaming(false) + setStopMsg(false) + setCurrentResp(null) + currentRespRef.current = null + return }
🧹 Nitpick comments (4)
frontend/src/routes/_authenticated/integrations/apiKey.tsx (1)
256-260
: Keep user-facing errors generic, but log details for debuggingAdd console.error in these catch blocks to preserve diagnostics while showing a generic toast. The create path currently loses the error context.
} catch (error) { + console.error("Failed to create API key:", error) toast({ title: "Error", description: "Failed to create API key", variant: "destructive", })
} catch (error) { + console.error("Failed to revoke API key:", error) toast({ title: "Error", description: "Failed to revoke API key", variant: "destructive", })
Also applies to: 294-298
frontend/src/hooks/useChatStream.ts (3)
227-235
: Minor: ensure cleanup releases reference to EventSourceSet currentEventSource = null so it can be GC’d and to avoid stale checks in future attempts.
const cleanup = () => { if (currentEventSource) { currentEventSource.onopen = null currentEventSource.onerror = null if (currentEventSource.readyState !== EventSource.CLOSED) { currentEventSource.close() } + currentEventSource = null } }
292-305
: Handle non-CLOSED onerror to avoid a potentially hanging PromiseIf onerror fires while readyState is CONNECTING and the connection never recovers, the promise can remain unresolved. Consider retrying with backoff here too (still keeping ES’s auto-reconnect as first try).
Example:
- es.onerror = async (e) => { + es.onerror = async (e) => { clearTimeout(connectionTimeout) if (isResolved) { // If already resolved, don't handle the error here return } - // Check if EventSource is in a failed state - if (es.readyState === EventSource.CLOSED) { - cleanup() - await tryRefreshAndRetry() - } + // If closed, or repeatedly erroring while connecting, retry + if (es.readyState === EventSource.CLOSED) { + cleanup() + await tryRefreshAndRetry() + } else { + // Optional: small backoff before forcing a retry if not opening soon + setTimeout(() => { + if (!isResolved) { + cleanup() + tryRefreshAndRetry() + } + }, 1000) + } }
276-283
: Optional: make the 5s connection timeout configurableNetworks and proxies vary. Consider a parameter or env to tune this without code changes.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
frontend/src/hooks/useChatStream.ts
(3 hunks)frontend/src/routes/_authenticated/agent.tsx
(2 hunks)frontend/src/routes/_authenticated/integrations/apiKey.tsx
(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/src/hooks/useChatStream.ts (2)
frontend/src/utils/streamRenderer.ts (1)
cleanup
(247-253)server/utils.ts (1)
delay
(137-138)
🔇 Additional comments (1)
frontend/src/hooks/useChatStream.ts (1)
420-423
: Generic error toasts align with the new patternConsistent with PR goal. No issues.
Also applies to: 1045-1048
## [3.18.1](v3.18.0...v3.18.1) (2025-10-16) ### Bug Fixes * **eventsource:** Make EventSource creation in frontend more robust with retry mechanism ([#1113](#1113)) ([9d1711c](9d1711c))
Description
Make EventSource creation more robust with retry mechanism.
Testing
Tested locally.
Summary by CodeRabbit