bigskysoftware / bigskysoftware/htmx-extensions

SSE reconnect never gives up and retries without jitter

Open
#192 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
JavaScript
Stars
284
Forks
88
PR merge metrics
No merged PRs in 30d

Description

## Summary

`htmx-ext-sse@2.2.4` (and `src/sse/sse.js` on `main`) still reconnects forever with no jitter after `EventSource.CLOSED`. The old XOR backoff (`2 ^ retryCount`) was fixed in 2.2.1; these two problems replaced it.

Happy to open a PR if you want one. CONTRIBUTING prefers an issue first for discussion, so this stops here until you say otherwise.

## Current code

`ensureEventSource`'s `source.onerror` in [`src/sse/sse.js`](https://github.com/bigskysoftware/htmx-extensions/blob/main/src/sse/sse.js) (same in the 2.2.4 npm file):

```js
if (source.readyState === EventSource.CLOSED) {
retryCount = retryCount || 0
retryCount = Math.max(Math.min(retryCount * 2, 128), 1)
var timeout = retryCount * 500
window.setTimeout(function() {
ensureEventSourceOnElement(elt, retryCount)
}, timeout)
}
```

## 1. No give-up

`Math.min(retryCount * 2, 128)` caps the *delay* at 64 seconds (`128 * 500`). There is no maximum-attempts check. A permanently unreachable endpoint is retried forever at 64s intervals for as long as the element stays in the DOM.

`onopen` resets `retryCount` to `0` after a successful reconnect, which is good for a transient outage. It does not bound a never-recovering endpoint.

## 2. No jitter

`Math.random()` went away with the XOR expression in 2.2.1. Every client that lost the connection at the same moment now retries in lockstep: 0.5s, 1s, 2s, 4s, … A server that just came back gets a thundering herd.

## Not this issue

2.0.0–2.2.0 used `Math.random() * (2 ^ retryCount) * 500` plus `Math.min(7, retryCount + 1)`. That XOR / capped-counter bug is already gone. Please do not treat this as a request to restore that expression.

## Suggested shape (not a patch)

- Stop after a finite number of failed attempts (or expose a max-attempts option; `Infinity` can stay the default if you want today's behavior).
- Add jitter around the exponential delay so clients desynchronize.
- Keep the existing successful-open reset so a recovered stream does not stay at the 64s cap.

Verified against npm `htmx-ext-sse@2.2.4` (2025-10-18) and `bigskysoftware/htmx-extensions` `main` `src/sse/sse.js`.

Contributor guide

Open the contributing guide

Research direction

Start in src/sse/sse.js at ensureEventSource's source.onerror handler and inspect the existing reconnect flow, including the onopen retry reset. Define and implement a finite failed-attempt policy and jittered exponential delay without restoring the old XOR expression; done means retries can stop, simultaneous clients can desynchronize, and successful opens still reset the retry state.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.