re-frame 2024-03-08

Hey, I'm playing around with flow and find it really nice. But I've run into a problem. My flows works the first time the :inputs gets data, then those paths are cleared and the next time data arrives at the paths, my flows are not doing their thing. Any tips on how I can debug?

Thank you @kimo741! I'm currently playing with flows in a larger app. I haven't reproduce the behavior I mentioned about, but I think I understand why I got it. I think I had some namespaces pointing at alpha and some at core as I did't understood the difference between them. So some of my effects had the flow interceptor and some didn't. Do you agree that this setup could cause this behavior? Don't think it's an option for me to change all of the namespaces from core to alpha, instead, do you think using the (rf/reg-global-interceptor re-frame.flow.alpha/interceptor) is an alternative? Just for context. The scenario is about session management. So the server sends data about when session started and for how long the session is valid for. Flow calculates ::renew-session?, ::session-about-to-expire? and :session-expired? . I think the flow code is very elegant and minimalistic, easy to test and as the data as it always inside the app-db it's REPL friendly.

do you think using the (rf/reg-global-interceptor re-frame.flow.alpha/interceptor) is an alternative?
TLDR - make sure your app registers flow/do-fx and flow/interceptor as the last 2 global interceptors. And always call the original re-frame.core/reg-event-db, not the alpha version. I thought about making it a global interceptor in re-frame - the issue is, for reliability, you have to make sure it's the final global interceptor. But if the user registers their own global interceptors, then flow/interceptor tends to be the first global interceptor. In that case, interceptors passed into reg-event-db would precede flows in the queue, while global interceptors would succeed them. Too complex, IMO - especially since flow/interceptor changes the :db effect. Different interceptors would get different versions of the db. I see the usability problem of requiring re-frame.alpha everywhere. Maybe there's another decent solution we haven't though of yet...

make sure your app registers flow/do-fx and flow/interceptor as the last 2 global interceptors.
Is there a simple way doing this? I created a small project https://github.com/jherrlin/learn-re-frame-flow where I took out the essential pieces from the other project. In this case there is only a single global interceptor. This show's how I intend to use flows though.

I'm not yet sure why, but if I register the flow interceptor to global interceptors it works. But I think that somehow this should be done automatically.

;; Reg flow interceptor
(rf/reg-global-interceptor re-frame.flow.alpha/interceptor)

Interesting, it does sound like a potential bug. What exactly do you mean by "cleared" and "arrives"? One thing comes to mind - make sure to use re-frame.alpha everywhere in your app, not re-frame.core. If you call the usual re-frame.core/reg-event-db, for instance, you'll register an event handler with the flow interceptor missing... which could explain why your workaround fixes it. > Any tips on how I can debug? Maybe you could fork re-frame and add a minimal repro into the todomvc example?

Maybe add a module? src/load_flows.cljs:

(ns load-flows (:require [re-frame.core :as rf] 
                         [re-frame.flow.alpha :as flow]))
(rf/reg-global-interceptor flow/do-fx)
(rf/reg-global-interceptor flow/do-fx)
shadow-cljs.edn:
{:deps     true
 :http     {:port 8081}
 :dev-http {8280 "resources/public"}
 :builds
 {:frontend
  {:target     :browser
   :asset-path "/js"
   :output-dir "resources/public/js"
   :modules    {:main {:init-fn main/init}
                :load-flows {:depends-on [:main]}
                             :entries [load-flows]}}}}}

Nice! This looks super good when using shadow. Our production build is not using shadow though, but maybe something similar is possible in our build step.