figwheel-main

figwheel-main http://figwheel.org
dominicm 2020-07-09T11:56:54.479500Z

I rebase many times a day, or switch branches, I seem to break my build whenever I do. I get weird errors, usually with broken JS output or similar. How can I resolve this?

dominicm 2020-07-09T11:57:07.479600Z

I'm guessing there's no debounce or something

bhauman 2020-07-09T12:33:53.480Z

@dominicm I’m pretty sure there is a debounce

bhauman 2020-07-09T12:34:07.480200Z

maybe its not long enough?

dominicm 2020-07-09T12:34:34.480300Z

do debounces go into a queue? They should wait for the previous build to finish, if they don't.

dominicm 2020-07-09T12:36:28.480900Z

I'll look at what throttle does :)

bhauman 2020-07-09T12:36:45.481300Z

it basically says if there are no changes in 50ms

bhauman 2020-07-09T12:36:58.481600Z

then continue I think

dominicm 2020-07-09T12:37:43.481700Z

right, so no prevention of overlap

dominicm 2020-07-09T12:37:55.481800Z

So your build has to be <50ms otherwise 💥

bhauman 2020-07-09T12:38:10.482100Z

no between each file change

dominicm 2020-07-09T12:38:29.482500Z

Let me re-read, I must have misunderstood

dominicm 2020-07-09T12:38:43.482800Z

that's not my interpretation of it

bhauman 2020-07-09T12:38:45.482900Z

it runs on the assumption that the time between files changes is small and if it’s exceeded

bhauman 2020-07-09T12:39:13.483200Z

hmmm

dominicm 2020-07-09T12:39:39.483300Z

yeah, I'm still reading it as not be a debounce. It basically just sleeps 50ms from the first event coming in.

dominicm 2020-07-09T12:41:01.483600Z

I should double check my terminology, I know there's a distinction from debounce/throttle, but I forget repeatedly

dominicm 2020-07-09T12:41:47.484Z

yeah, this has 2 big bold definitions. This is a throttle: > Throttling enforces a maximum number of times a function can be called over time. As in “execute this function at most once every 100 milliseconds.” except 50ms

dominicm 2020-07-09T12:41:59.484100Z

> Debouncing enforces that a function not be called again until a certain amount of time has passed without it being called. As in “execute this function only if 100 milliseconds have passed without it being called.” This is what you described

bhauman 2020-07-09T12:42:31.484400Z

yeah it should be named debounce

dominicm 2020-07-09T12:42:43.484800Z

Hmm, no. I'm saying the name is right. It behaves as a throttle?

bhauman 2020-07-09T12:42:43.484900Z

dang that algorithm is hard to read first thing in the morning

bhauman 2020-07-09T12:43:37.485300Z

ok yeah I guess it is a throttle

dominicm 2020-07-09T12:44:37.485600Z

Either way, neither prevents overlapping builds.

bhauman 2020-07-09T12:44:51.485900Z

thats true

dominicm 2020-07-09T12:45:19.486Z

You'd need a lock or queue to prevent that.

bhauman 2020-07-09T12:46:28.486600Z

wait a second

bhauman 2020-07-09T12:47:02.487Z

hmmm OK yep

bhauman 2020-07-09T12:47:17.487300Z

this should be easy enough

dominicm 2020-07-09T12:47:28.487400Z

Great. 😁

bhauman 2020-07-09T13:01:22.488Z

@dominicm

bhauman 2020-07-09T13:01:27.488300Z

(defn throttle [millis f]
  (fn [{:keys [collector] :as ctx} e]
    (let [collector (or collector (atom {}))
          {:keys [collecting? events]} (deref collector)]
      (if collecting?
        (swap! collector update :events (fnil conj []) e)
        (let [events (volatile! nil)]
          (swap! collector #(-&gt; %
                                (assoc :collecting? true)
                                (update :events (fn [evts] (vreset! events evts) nil))))
          (future
            (f (cons e @events))
            (Thread/sleep millis) ;; is this needed now?
            (swap! collector assoc :collecting? false))))
      (assoc ctx :collector collector))))

bhauman 2020-07-09T13:14:54.488700Z

@dominicm deployed the fix to 0.2.10-SNAPSHOT

bhauman 2020-07-09T13:15:05.488900Z

thanks for prompting me on that

dominicm 2020-07-09T13:16:22.489100Z

hum, that doesn't look right to me. Doesn't that call f straight away?

bhauman 2020-07-09T13:16:36.489400Z

yes but it works

bhauman 2020-07-09T13:16:51.489700Z

well I changed it

bhauman 2020-07-09T13:16:59.490Z

(defn throttle [millis f]
  (fn [{:keys [collector] :as ctx} e]
    (let [collector (or collector (atom {}))
          {:keys [collecting? events]} (deref collector)]
      (if collecting?
        (swap! collector update :events (fnil conj []) e)
        (let [events (volatile! nil)]
          (swap! collector assoc :collecting? true)
          (future
            (try
              (Thread/sleep millis) ;; is this needed now?
              (swap! collector update :events (fn [evts] (vreset! events evts) nil))
              (f (cons e @events))
              (finally
                (swap! collector assoc :collecting? false))))))
      (assoc ctx :collector collector))))

bhauman 2020-07-09T13:17:43.490600Z

when collecting? is true things get collected, and f is blocking

dominicm 2020-07-09T13:18:46.490900Z

ah, so it cleans up at a different time, nice. Subtle.

bhauman 2020-07-09T13:19:44.491500Z

less machinery and relying heavily on the properties of atom

dominicm 2020-07-09T13:20:18.491600Z

Does the event list grow forever? I just noticed that.

bhauman 2020-07-09T13:20:41.491800Z

(swap! collector update :events (fn [evts] (vreset! events evts) nil))

bhauman 2020-07-09T13:20:55.492200Z

sets it to nil

bhauman 2020-07-09T13:21:24.492700Z

relying on swap to grab the current events and delete them atomicly

dominicm 2020-07-09T13:22:12.492900Z

ah, I see. And then any that come in during f will be collected and in the queue for later, great!

bhauman 2020-07-09T13:22:50.493400Z

yeah it was right there, I guess I was tired/lazy when I was initially coding it??

bhauman 2020-07-09T13:23:06.493700Z

so similar to the original version

dominicm 2020-07-09T13:23:37.494Z

There's a lot of considerations to factor in this little function. State is really hard.

dominicm 2020-07-09T13:23:47.494100Z

Those 15 loc are thick with meaning.

bhauman 2020-07-09T13:26:20.494400Z

can’t argue with that

bhauman 2020-07-09T13:26:41.494700Z

but its really nice to have that fixed

bhauman 2020-07-09T13:28:23.495400Z

@admin055 I got rid of the dependency on create-react-class so that’s no longer a problem

bhauman 2020-07-09T13:29:01.496200Z

I’m now going to install android … which I was avoiding until now

2020-07-09T14:11:03.496900Z

@bhauman Perfect, thx for the information.

2020-07-09T14:24:45.498500Z

> Thanks for trying this out @admin055 > I really need this early feedback to work out the last bugs.  Sorry I > didn’t try this with android.  It’s such a large setup time. it's always a pleasure to use and test your work. I'll retry today later and let you know.

2020-07-09T15:00:49.001300Z

Thx @bhauman, all works perfect on Android emulator for me now. For Android emulator and real devices, we must only do on more command: adb reverse tcp:9500 tcp:9500 to get access to:

<http://localhost:9500/cljs-out/android/cljsc_opts.json>

bhauman 2020-07-09T15:01:10.001500Z

heck yes!

2020-07-09T15:02:18.001800Z

Last night it was too late i didn't even think about that! :)

2020-07-09T15:06:30.002300Z

Android real device test checked ✔️

bhauman 2020-07-09T15:09:58.002800Z

oh really wow

bhauman 2020-07-09T15:10:36.003400Z

Would you want to add android notes to the react native figwheel docs?

2020-07-09T15:11:53.003900Z

Yes of course

bhauman 2020-07-09T15:12:02.004100Z

awesome!

bhauman 2020-07-09T15:12:53.004700Z

also you may want to try the :launch-js configuration and see how it works?

bhauman 2020-07-09T15:13:38.005500Z

especially if when you stop figwheel and relaunch

bhauman 2020-07-09T15:14:00.005900Z

without closing metro or android

bhauman 2020-07-09T15:14:06.006100Z

it should just work

2020-07-09T16:43:00.006400Z

@bhauman > Would you want to add android notes to the react native figwheel docs? PR done. > also you may want to try the :launch-js configuration and see how it works? Work perfectly, nice work!

bhauman 2020-07-09T18:55:52.006800Z

This is fantastic! Great!

👍 1