Skip to content

Enhancement: SSE reconnection with exponential backoff #366

@jhodapp

Description

@jhodapp

Problem

When the Rust backend restarts during a deploy, the SSE EventSource connection receives an HTTP 500 and enters the CLOSED state (readyState = 2). The current implementation in src/lib/hooks/use-sse-connection.ts closes the connection permanently and sets an error state — it never retries.

This means users lose real-time updates (action/agreement/goal change notifications) until they manually refresh the page.

Current behavior

In use-sse-connection.ts:

  • readyState === EventSource.CONNECTING → browser auto-retries (network errors)
  • readyState === EventSource.CLOSED → connection is closed permanently, no retry

Proposed solution

Add manual reconnection with exponential backoff when the EventSource enters the CLOSED state due to a server error (500/502/503). Key considerations:

  1. Exponential backoff with jitter — base delay 1s, max 30s, add random jitter to prevent thundering herd when many clients reconnect after a server restart
  2. Max retry limit — stop after ~8 attempts to avoid infinite retry loops
  3. Reset on success — clear retry counter when connection is re-established
  4. Don't retry on auth errors — 401/403 should still close permanently (the current force_logout SSE event handles this)
  5. Consider migrating from native EventSource to fetch + ReadableStream — native EventSource cannot send custom headers (API version header), and the retry behavior is browser-dependent

Files to modify

  • src/lib/hooks/use-sse-connection.ts — add retry logic
  • src/lib/stores/sse-connection-store.ts — potentially track retry count/state

Research notes

  • Native EventSource behavior on HTTP 500 varies by browser (spec says CLOSED, most browsers agree)
  • @microsoft/fetch-event-source is the most popular library for controlled SSE (~1.5M weekly downloads) but hasn't been updated since 2023
  • A manual fetch + ReadableStream implementation avoids the dependency and gives full control over headers and retry

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementImproves existing functionality or featuregood first issueGood for newcomers

    Type

    Projects

    Status

    🔖 Ready

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions