Skip to content

Conversation

kalpadhwaryu
Copy link
Contributor

@kalpadhwaryu kalpadhwaryu commented Oct 15, 2025

Description

Make EventSource creation more robust with retry mechanism.

Testing

Tested locally.

Summary by CodeRabbit

  • New Features
    • Adds automatic reconnection for chat streams with token refresh, exponential backoff, and a 5-second connection timeout, improving reliability after transient failures.
  • Bug Fixes
    • Prevents stale or overlapping stream connections by cleaning up previous sessions before retrying.
    • Reduces rapid retry loops, improving stability when starting streams.
  • Refactor
    • Standardizes error toasts to use a generic title and description for stream failures.
    • Simplifies API key error messages for create and revoke actions to consistent, user-friendly text.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @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

  • Robust EventSource Creation: Implemented a comprehensive retry mechanism with exponential backoff and a 5-second connection timeout for EventSource connections, particularly after token refresh attempts, to significantly improve connection reliability.
  • Generalized Error Messages: Updated error toast notifications across multiple frontend components to display more user-friendly and generic messages (e.g., "Something went wrong. Please try again." or "Failed to create API key") instead of specific technical error details.
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 15, 2025

Walkthrough

Adds 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

Cohort / File(s) Summary of Changes
SSE retry and token refresh in chat stream
frontend/src/hooks/useChatStream.ts
Introduces createAuthEventSource retry logic with token refresh, exponential backoff, per-attempt cleanup, 5s connection timeout, and revised error handling/messages. Maintains success path while ensuring teardown and controlled retries on failures.
Agent route toast message updates
frontend/src/routes/_authenticated/agent.tsx
Replaces specific EventSource failure toasts with generic "Error" title and "Something went wrong. Please try again." description in two catch blocks. No behavioral changes beyond user-visible text.
API key error handling standardization
frontend/src/routes/_authenticated/integrations/apiKey.tsx
Simplifies error toasts to fixed descriptions for create/revoke API key actions, removing conditional use of error.message.

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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • zereraz
  • shivamashtikar
  • junaid-shirur

Poem

A hare with packets on the breeze,
Retries hop in threes and threes—
Backoff beats, a gentle drum,
Tokens fresh, the streams still hum.
If storms arrive, I’ll clean and try—
Five heartbeats pass, then up I fly.
Carrots cached; connections nigh. 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly and concisely describes the main change by indicating that EventSource creation in the frontend will be made more robust through a retry mechanism, matching the detailed updates to SSE connection logic in the changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix-EventSource-create-error

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a 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.

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 fails

Early 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 fails

If 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 debugging

Add 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 EventSource

Set 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 Promise

If 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 configurable

Networks 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

📥 Commits

Reviewing files that changed from the base of the PR and between 8b2c8d8 and c4b6799.

📒 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 pattern

Consistent with PR goal. No issues.

Also applies to: 1045-1048

@shivamashtikar shivamashtikar merged commit 9d1711c into main Oct 16, 2025
4 checks passed
@shivamashtikar shivamashtikar deleted the fix-EventSource-create-error branch October 16, 2025 13:35
Aayushjshah pushed a commit that referenced this pull request Oct 16, 2025
## [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))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants