tfwright

tfwright

There has been discussion in various threads around how to handle cases where the user might be in the middle of some work at a URI that uses LiveView when a deployment occurs. This causes the LiveView process to restart and potentially, the user to lose their work.

In my case, I have a fairly complex view that allows the user to ‘select’ various elements with the selections stored in the LV state. On a deployment, this state is lost causing the LV to review to the blank state.

The docs offer some guidance for state recovery that focuses on forms, using the pxh-auto-recover binding:

On the server, the "validate_wizard_step" event is only concerned with the current client form data, but the server maintains the entire state of the wizard. To recover in this scenario, you can specify a recovery event, such as "recover_wizard" above, which would wire up to the following server callbacks in your LiveView

I assume this only works for forms. My question is, what about other cases of state? Can I use that binding on non form elements to recover other state? And how is the server expected to “maintain” the state (of the form or anything else)? In some sort of persistent storage it can read from even after a restart?

Thanks!

Showing Posts 1 to 5

LostKobrakai

LostKobrakai

Anything non persistent will be gone after restart, so yes you need a persistent storage.

Why would you think so? Any data your liveview process knows about can be persisted – even if just using :erlang.term_to_binary/:erlang.binary_to_term. You could use other means of serialization into your datastore, those might not support any erlang term.

How exactly you architect a solution here depends heavy on your problem though. You could use ecto/dets/mnesia or many other persistent data storages and each come with certain tradeoffs you have to decide on.

tfwright

tfwright OP

I was just extrapolating from the examples and my experience with other bindings that are form specific (like phx-change). I should have tested that assumption before posting here though. I’ll give it a shot now.

tfwright

tfwright OP

I can’t seem to trigger the recover event. Here’s what I tried:

  1. Set code_reloader: false on my endpoint config, as per documentation.

  2. Added phx-auto-recover="recover" in the outermost div of my LV template.

  3. Added the following to my LV module:

      def handle_event("recover", _params, socket) do
        IO.warn("recovering!")
        {:noreply, socket}
      end

After that I tried aborting and then restarting the server process. After the abort, I saw the socket attempt to reconnect, adding the loading class as expected, but after I restarted it loaded the blank state and I did not observe any warning text in the logs.

Any idea what I’m doing wrong?

tfwright

tfwright OP

I managed to work out a solution for this without using LiveView’s built in form auto-recovery feature, and it turned out to be pretty straightforward. Here are the steps in case anyone else is looking to do something similar:

  1. After playing around a bit with mnesia, I decided to use @lucaong’s CubDB instead because I just needed a very simple persistent KV store. CubDB has been serving that purpose admirably so kudos and thanks to @lucaong.

  2. Added CubDB db to my app’s supervisor:

       {CubDB, data_dir: Application.get_env(:my_app, :cubdb_data_dir), name: MyApp.RecoveryCache}
    
  3. Added a binding for my “selection” event and a handler in my LV module that stores the resulting state:

     CubDB.put(MyApp.RecoveryCache, {:selections, user_id: socket.assigns.current_user.id}, selections)
    
  4. Added some conditional code in the mount handler that checks for existing cache and adds it to the LV assigns:

    socket =
     if connected?(socket) do
       selections =
         CubDB.get(
           MyApp.RecoveryCache,
           {:selections, user_id: socket.assigns.current_user.id}
         )
    
       socket |> assign(selections: selections)
     else
       socket
     end
    

That’s it! Now after making some selections on the page and either deploying the app, restarting the server, or just reloading the page, the previous selections are magically still there! Amazing.

tfwright

tfwright OP

Another thing to keep in mind I haven’t seen mention in this context (maybe because it’s so obvious) is to consider whether the state in question is simple enough to store in the url, and makes sense there. Because with push_patch and handle_params you can get state restoration for basically free that way.

I was most of the way through persisting a simple index to disk before I thought of this… :expressionless:

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
apz
I’m new to elixir and just tried to install the elixirLS extension for VScode(ium) and it is throwing some errors that I would like help ...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews