I have a Phoenix LiveView app running in production at https://indiepaper.me. I use fly.io for deployment and Cloudflare as a proxy.
I deploy using rolling release and I have noticed that whenever a new release is pushed the WebSocket disconnects and the page fully reloads. It would not have been that much of an issue, but I have a Markdown Editor LiveView page that sends JSON through
pushEvent and when the LiveView disconnects and the page reloads I lose all that state.
Is this an issue with LiveView or is Cloudflare causing that issue ?
When you start a new version of your application, the process that was handling the websocket connection for your liveview terminates. All the state that was in the liveview server-side process memory is lost, and the server’s end of the websocket’s connection disappears. In a normal shutdown, the server will send a disconnect to the client’s websocket, and the client will try to reconnect.
Even if the server is killed abruptly and the socket stays “half-open”, the phoenix websocket client has a keepalive mechanism that regularly sends heartbeat messages to the server to discover when the liveview process is down or not reachable. By default this happens every 30 seconds (phoenix/socket.js at 940664cd5af6528c5e4beef204e040dd27e4febf · phoenixframework/phoenix · GitHub). So if your server-side LV process is gone, the client will eventually notice and reconnect.
If I understand you correctly, your LiveView application has some JS that keeps local state on the client’s side. If you want this state to persist at the client across LiveView reconnects, maybe one option would be to store it in the client’s local storage (Window.localStorage - Web APIs | MDN)
I hope this helps
Thanks for the in-depth explanation, local storage seems like the way to go.
The page shouldn’t reload unless the page detects and unrecoverable state like multiple failed mounts after a reconnect (or you added your own reconnect logic based on the
static_changed? helper for refreshing the page when new assets are deployed. If you have
liveSocket.enableDebug() enabled in the js console, it may tell you more when the refresh happens.
I have enabled
liveSocket.enableDebug() on Staging deployment and a
timeout error, doing a hard refresh error flashed on the console before doing a hard refresh.
I"m using the default Canary release strategy on Fly, I think the time between VM restarts are what causing the issue. What deployment strategy should I be using ?
I think that, full page reload or not, after your socket reconnects the state that was stored in the LV process will be lost, and that seems to be the crux of the problem here. In order not to lose the state, you have to persist it somewhere (either at the client, or on the server).