fix(reconnect): wire WS manual-reconnect helper now that htmx is actually loaded #88
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/ws-reconnect-after-restart"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
htmx.defineExtension('lc-ws-reconnect', ...)andhtmx.config.wsReconnectDelaywere called from an inline body<script>, which executes during body parsing - before the deferredhtmx.min.js/htmx-ext-ws.jsin<head>have run.window.htmxwasundefined, theif (window.htmx)guards silently skipped both setups, andwindow.__lcReconnectWSwas never defined.1006/1012/1013. Adocker stop/ redeploy closes the socket cleanly with1000/1001, so the extension does nothing AND the manual-reconnect fallback didn't exist. The banner sat on "Reconnecting..." forever and the page had to be reloaded manually.DOMContentLoaded(fires after deferred scripts), drop the extension-mechanism dance, read htmx'shtmx-internal-dataproperty directly to callwrapper.init(), and splitwsErrorfromwsCloseso onlywsClose(which actually carries a code) decides whether to fire the manual reconnect.Test plan
just dev-web-down && just dev-web(graceful restart). Banner should show "Reconnecting...", then "Connected", and the page should soft-refresh without a manual reload.docker kill) so the close code is1006. Should also reconnect on backoff.close(4000, 'lc-half-open'). Reconnect should still kick in.just checkclean.`htmx.defineExtension('lc-ws-reconnect', ...)` and `htmx.config.wsReconnectDelay` were called from an inline `<script>` in the body, which the parser executes *during* body parsing - before the deferred `htmx.min.js` and `htmx-ext-ws.js` in `<head>` have had a chance to run. `window.htmx` was therefore `undefined` at the point of those calls, the `if (window.htmx)` guards silently skipped both blocks, and `window.__lcReconnectWS` was never defined. That hid a much more visible bug: the htmx-ext-ws extension only auto-reconnects for close codes `1006/1012/1013`. When the server is restarted gracefully (SIGTERM via `docker stop` / a redeploy), the socket closes with `1000`/`1001` instead, so the extension does nothing AND the manual-reconnect fallback was never wired up. The page would sit on "Connection lost. Reconnecting..." forever and the user had to reload to recover. Defer the htmx-dependent setup to `DOMContentLoaded` (which fires after every deferred script in the document has executed, so `window.htmx` is guaranteed). Drop the extension-mechanism dance entirely: `__lcReconnectWS` now reads htmx's `htmx-internal-data` property on the `[ws-connect]` element directly to call `wrapper.init()`. Also separate the `wsError` and `wsClose` listeners so only `wsClose` (which carries the close code) decides whether to fire the manual reconnect; `wsError` arrives without a code and was previously triggering an immediate, backoff-bypassing reconnect that overlapped with the close-driven retry. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>