day8 / re-frame-10x

A debugging dashboard for re-frame. X-ray vision as tooling.
MIT License
631 stars 68 forks source link

Events that return app-db unchanged seem to cause the event history to lag #268

Closed stumitchell closed 1 year ago

stumitchell commented 4 years ago

We created a situation where the Event Tab was showing trace for the "Last event", not the "current event". There was a one-event lag.

An event handler written with an implied do seems to be the cause. Eg:

(re-frame/reg-event-db
 :event
 (fn-traced [db _]
   (let [a 10                               ;; <-- implied do with two forms  (see db below)
         b (+ a 20)]
     (+ a b))
   db)))
jtlocsei commented 3 years ago

This might be unrelated, but could it be that you didn't yet have a subscription that uses the data that's updated in the db by the event? It seems like the refresh of re-frame-10x display is triggered by data flow in a subscription. I had was seeing a one-event-lag and it was fixed when I added the subscription. Jacek Schae talks about the issue briefly at the end of Video 8 in his free re-frame course https://www.jacekschae.com/learn-re-frame-free (no affiliation)

superstructor commented 2 years ago

@MawiraIke Have a look at this please.

MawiraIke commented 2 years ago

I can reproduce this issue in the latest re-frame-10x version (1.2.7) although it's somehow different now. Using the todos app, there is a delay in showing the trace for the latest event, i.e

(re-frame/reg-event-db
 :event
 (fn-traced [db _]
   (let [a 10                               ;; <-- implied do with two forms  (see db below)
         b (+ a 20)]
     (+ a b))
   db)))

although the delay ends after clicking any part of the window. Afterwards, the event tab updates to show the most recent trace.

kimo-k commented 1 year ago

Hey @stumitchell, interesting case. I don't think this is caused by the implicit do, though. Rather, this behavior arises when the new app-db is identical to the old one.

This doesn't work:

(reg-event-db :bad-event (fn [db _] db))

While this does:

(reg-event-db :good-event (fn [db _] (assoc db ::gensym (gensym))))

We accumulate trace at various sites, but only once do we express a quiescent trace. Reagent's render queue should invoke this in its final loop as it handles a reset of the app-db. The problem is, there is no reset. Nothing is scheduled, no quiescence.

Without quiescence, there is no match until the next epoch begins. In other words, 10x batches the event, thinking there are more soon to come.

I think this is a complete picture, but I'm still not sure what to do about it. I made a test branch, which makes all events return a new app-db. This may be intrusive for the user, though, and it seems inelegant.

kimo-k commented 1 year ago

I found an obvious solution based on the above analysis. An unchanged :db effect can be considered a new moment of quiescence, despite reagent taking no action. It's straightforward to trace this moment.