Liveview constantly refreshes page on poor connection

Hello,

My app is running in production with a few liveview pages. Customers in regions known to have poor connection have reported that the liveview pages constantly refresh on a 10 second or so interval. I was not able to reproduce the issue myself, but I was able to force the app into the refresh cycle by including :timer.sleep(10000) in the mount/3 callback. My thinking was this would simulate a shaky connection, and indeed it forced me into the same sort of refresh loop.

I have a few questions

  • Is there anything I can do about this? I am going to have users in regions of poor connection. Is there a way to gracefully degrade the liveview page for users who are not able to get a strong connection? If not, I may have to completely sunset use of liveview in my application, which is not something I want to do.
  • What is liveview’s failsafe mode? After 10 refreshes the debugger mentioned that it was putting itself in failsafe mode, which didn’t actually seem to change the behavior. I was still getting put into a refresh loop.

Any help would be appreciated! After exploring liveview for 6 months or so in a production environment, the biggest barrier to full adoption is the fact that it does not seem to gracefully degrade. Putting a page into a refresh loop every 10 seconds is not a useable experience.

A sleep does not really simulate a poor connection. We are reloading the page because the default timeout for a channel join (thus a LV mount) is 10s. This value can be bumped higher via the live socket constructor

new LiveSocket("/...", {timeout: 15000})

However, it seems less likely that your users are frequently taking a 10s round trip to the server. Are you doing any potentially longer blocking work on mount? You can accurately simulate poor network links with latency and packet loss to test a truly poor connection. OS X as a network link condition app, and I’m sure other systems do as well. You can also run these commands on osx:

# enable myapp.local 100ms latency 30% pkt loss
$ sudo -i
$ dnctl pipe 1 config bw 10Mbit/s delay 100 plr 0.3
$ echo "dummynet out proto tcp from any to myapp.local pipe 1" | pfctl -f -
$ pfctl -e

# disable
$ pfctl -f /etc/pf.conf && pfctl -d && dnctl -q flush

How edge are your users? If they consistently see 10s RTT then that will be a barely usable experience no matter what technology choices you make. Simulating 30% packet loss on LiveView applications yields a surprisingly solid experience for me, so we’d need to know more about their conditions and if your own mount is adding to the round trip latency.

6 Likes

One thing that can lead to spotty experience when there is frequent connects / disconnects are live view pages that aren’t coded to recover their state very well. Good examples are modals or other major UI elements that are present / absent on the basis of an assign that isn’t backed by a URL param or form element. If the user disconnects / reconnects, the liveview state is lost and the UI will “glitch” back to the base state.

I’d make sure that any user facing UI states are backed by something client side so that your live view can recovery cleanly.

3 Likes

Hi @chrismccord, thank you for the detailed response. It’s definitely possible that the work I am doing on mount is taking a while on mount. I’m going to try bumping the timeout up to see if that settles things, and will also look for ways to optimize the work done in mount.

The poor network simulation code provided looks promising and quite helpful – I’d not have thought of that on my own, so thank you!

@benwilson512 I agree with you here, and I’ve been making heavy use of URL params to ensure the state is recoverable. Unfortunately, for some users, the refresh occurs so often that it’s not even possible to accomplish meaningful work. Were the refresh to happen sporadically, I could see the case in which recovering from URL params would be enough here, but I think I need to look a bit deeper into the root of why it is refreshing in the first place. Either way – thank you for the advice!