Keeping state when reconnecting to a different node (for example after deploying a new version of the application)

Hello,

I initially understood that keeping ui state (typically current user, navigation and the current form being filled) is provided out-of-the-box by Phoenix LiveView but the more I dig into the question, the more I get confused. To clear everything up, here are my questions:

  1. Can you confirm that by default, if a user switches to another node during a rolling deployment, all the transient state will be lost (with the exception of forms input that may be recovered in a wide number of situations).
  2. What are people doing in practice to deal with state recovery during rolling deployments? Is saving state in encrypted form on the client the recommended practice?
  3. Is there a hook allowing us to choose where assigns are stored? (for example to make it easy to use mnesia). Otherwise dealing with state recovery (whether state is stored on the client or elsewhere) seems to be very verbose and difficult to abstract.

Thank you!

2 Likes

In response to your original question:

  • #1 - yes.
  • #2 - it depends. Some clients will be fine with the built-in recovery, some will want to stash the state in a client-side token, some will use any of the various not-Liveview-specific BEAM strategies for persisting process state across restarts
  • #3 - assigns are stored in memory. If you want them stored someplace else, you’ll need to write that code. It could be as simple as writing {:noreply, save_assigns_someplace(socket)} everywhere instead of {:noreply, socket}

Another general thing to consider is that a specific LiveView process may not be the right place to store that state at all - for instance, if multiple users or tabs need to see in-progress changes it may be better to have the LiveViews involved all communicate with a single process (probably managed by DynamicSupervisor or similar).

4 Likes

Thanks for the insights, this was helpful, I will try to explore these hints. Just some quick remarks:

Some clients will be fine with the built-in recovery , some will want to stash the state in a client-side token, some will use any of the various not-Liveview-specific BEAM strategies for persisting process state across restarts

I see, thinking about it again, passing key parameters in the URL actually goes a long way in recovering state. This is the approach we’ve always used for our Javascript Single-Page-Applications where while state is stored on the client, there is a need to take into account the fact that mobile browsers tend to aggressively swap tabs put in the background and as a result the page is refreshed (and in-memory state lost) when the user comes back to it. Thinking about it, this is not very different from the present situation, yet keeping a basic authentication cookie on the client + using URL params has always been enough for us. Maybe the fact that the hosting model of Blazor/LiveView is so different from traditional technologies, may be leading us to overestimate the risk of finding ourselves in state management bankrupcy when it’s already too late to move back.

If you want them stored someplace else, you’ll need to write that code. It could be as simple as writing {:noreply, save_assigns_someplace(socket)} everywhere instead of {:noreply, socket}

Okay so to avoid claiming storage/memory twice, we’d then be using temporary_assigns to pass values to templates if I understand the idea correctly.

1 Like

Just a quick note to say I’ve cleaned up some of this thread.

@reddy, it’s usually best to wait at least 24 hours before bumping a thread, and if you must share feedback about the ecosystem please use the Ecosystem & Feedback section, thanks!

1 Like

I use to be full time C# programmer since C# 1.2 and just recently moved full time to TypeScript. You keep referencing Blazor meaning Razor Components aka Server-side Blazor. Anyway even if these technologies feel bit similar LiveView has been designed from the ground to up to work in server-side mode where with Blazor it was just a afterthought.
Let’s say you have to two Elixir nodes running your web site. In case of LiveView WebSocket connection gets disconnect from node-1 it can reconnect to node-2 because LiveView should handle this well.as LiveView was designed so that important state should be kept in client not on the server side. That means selected tab, open panels etc. Then that state is either stored in url or you can send you client side data when you reconnect through LiveSocket’s params field.

2 Likes