bigskysoftware / bigskysoftware/htmx-extensions
SSE reconnect never gives up and retries without jitter
- 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
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