Idea: persist liveview state across reconnections

If you only have a few things to save, then everything is easy. I save some LV state at client side too. It get harder when the state is complex, changing fast, and not easy to separate out those that need to be saved and those that don’t need to be saved. So, I am exploring the alternative, which is to save everything by default.

In the end, if you have 2 stateful programs (client and server) talking to each other, there is no panacea to cure out of sync problem that can arise from any number of reasons.

1 Like

Hello :wave:
This is very simple when state may go inside the URL params, basically you just parse the params on the action of your LV

  defp apply_action(socket, :index, params) do
    socket =
      |> assign_new(:columns, fn -> Jason.decode!(params["columns"] || "{}") end)
# etc

So you just do this whenever you update the state:

    socket
    |> push_patch(to: ~p"/url/?#{params}") # thanks ~p for being awesome

However, sometimes the data should not go inside the URL because we don’t want it to populate browser history, or because it doesn’t make sense when using bookmarks. In those scenarios it gets trickier.

Query params has a limitation on length that the server will accept, not ideal for large state.

I would suggest instead caching the state on the browser local storage and then loading via hooks on page load.

Less server resource utilisation in event you need to scale and you offload storage to the client. If there are breaking changes (such as changing key types) , you can also safely migrate or adjust the cached state with some migration logic, or simply drop them.

well you would not store Ecto structs in there for example, you should be storing only the minimum necessary. I just realized the question says “persist the full content of assigns somewhere”, and it is true that you would not do this for URL params.

For URL params you only want to add the pieces that are required for the server to restore the parts of the socket assigns that you wish to restore. Anything that does not belong to the socket assigns should not be calculated from URL params. Also you should only store state that is created due to the client-state, you do not want to store anything that should not leave the server.

What is the limitation on length?

The fly.io article is interesting, seems very robust with the small downside that it makes code a bit more complex and the initial page load is going to take an extra roundtrip to restore the state, this may or may not create a bit of a janky first-page load.

I believe you would be better served by an ETS cache in some scenarios, due to simplicity.