#Destroying lustre apps gracefully

1 messages · Page 1 of 1 (latest)

indigo knoll
#

I am interested in a method of destroying lustre apps safely. I have looked at doing it manually by communicating with events. However, in the situation that the element that the app is attached to is destroyed before any event is sent, I would like it to go through termination gracefully. I am also interested in internally shutting down the app from triggers within.

External Destruction: mount point

In this scenario the mount for the app is destroyed. Will it be possible to terminate the app?

Internal Destruction: final actions

In this scenario a signal is sent into the app informing that the app has been requested to terminate. This signal could also originate from the app's buttons. Is it possible for lustre apps to terminate from within controller functions?

fallow lily
#
let assert Ok(to_runtime) = lustre.start(...)

// at some later point

lustre.shutdown() |> to_runtime
indigo knoll
#

if I wanted to preform some action before shutdown occurrs would that be possible?

fallow lily
#

not without orchestrating it yourself somehow

indigo knoll
#

understood, I will look into it

#

thank you for lustre

fallow lily
#

i might do something like this

pub type Msg {
  AppRequestedShutdown(finally: Effect(Msg))
  ...
}

fn update(model, msg) {
  case msg {
    AppRequestedShutdown(finally) -> {
      #(model, effect.batch([
        // any other effects for graceful shutdown
        ...,
        finally
      ])
    }
  }
}
let assert Ok(to_runtime) = lustre.start(...)

// ... some time later

let shutdown = effect.from(fn(_) {
  lustre.shutdown() |> to_runtime
})

lustre.dispatch(AppRequestedShutdown(shutdown)) |> to_runtime

in general having effects in your message feels a bit weird but i cant think of another way you'd do it in this case

#

yeah not a very good shutdown story for lustre right now; i think you're the first to really want it

#

what's the scenario?

indigo knoll
#

I wanted to dynamically unload and load lustre apps

#

that was not an answer sorry

#

I was interested in covering HTMX's weakness in client side state to see if I could replace my usage of angular [with the combined htmx + lustre]. Lustre components seem to me to be the perfect solution to covering that weakness.

fallow lily
#

if you're using lustre components typically this would be handled declaratively by just removing the element from the DOM, but there are no lifecycle events or cleanup

#

@limpid steppe has also asked for this

indigo knoll
#

oh neat!

#

I will post what I find here (hopefully with a repo), thanks again for the help!

fallow lily
#

im open to the idea but i dont really have a good design that fits in with the rest of lustre so im leaving it for now

limpid steppe
#

(You summoned me, so I supposed it was expecting a response 😇)

indigo knoll
#

some minor updates

pub fn main() {
  // import plinth/browser/document
  let maybe_element = document.query_selector(app_selector)
  case maybe_element {
    Ok(element) -> {
      // import plinth/browser/element as dom_element
      // start (and restart) app on signal
      dom_element.add_event_listener(element, "start-external", fn(_) {
        let app = lustre.application(init, update, view)
        let assert Ok(app_runtime) = lustre.start(app, app_selector, Nil)
        let shutdown = effect.from(fn(_) { lustre.shutdown() |> app_runtime
      })

      // causes a crash (recoverable)
      dom_element.add_event_listener(element, "stop-internal", fn(_) {
        ExternalSignal(shutdown) |> lustre.dispatch |> app_runtime})

      // has not crashed yet
      dom_element.add_event_listener(element, "stop-external", fn(_) {
        lustre.shutdown() |> app_runtime})Nil})}
    Error(_) -> fn() { Nil }
  }

  Nil
}

Of course, the issue is now when htmx deletes the target element the event listeners attached with it go too.

A better solution would be to somehow expose main without calling it and to use hx-on triggers (on-load) on the exposed main function. Shutdown can occur with event listeners.

#

I am also considering web components to reload the shadow-dom on load.