From db0e84cdde46146ee7f9270a0f9583e98b1d4845 Mon Sep 17 00:00:00 2001 From: Ryan McCuaig Date: Tue, 7 Jul 2020 04:03:19 +0000 Subject: [PATCH] Add a polling fallback to filesystem watcher Changes to the latest beta version of macOS broke the mechanism that we're using to observe filesystem change events. It's more than just filesystem observation that has broken: any attempt to run a hot-reloading workflow crashes the Figwheel process with an uncaught exception at startup. (Note that build-once still works, since it doesn't try to access filesystem events). The underlying hawk library does have an implementation of a less-efficient polling watcher. Figwheel can use this to provide hot-reloading even when native events aren't available. This commit wraps the `hawk.core/watch!` function to catch any exception that's thrown, and re-try with the same options *except* that it explicitly starts a polling watcher. See also - https://github.com/gjoseph/BarbaryWatchService/issues/13 - https://github.com/java-native-access/jna/pull/1216 Part of #253. --- src/figwheel/main/watching.clj | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/figwheel/main/watching.clj b/src/figwheel/main/watching.clj index 5133e58..946172e 100644 --- a/src/figwheel/main/watching.clj +++ b/src/figwheel/main/watching.clj @@ -8,13 +8,23 @@ (def ^:dynamic *hawk-options* nil) +(defn watch-with-fallback! + "Wraps hawk/watch! to swap in a polling implementation if any of the native + OS file events interfaces fail." + [opts & groups] + (try + (apply hawk/watch! opts groups) + (catch Exception e + (prn e "WARN - no native fs events; falling back to polling filesystem") + (apply hawk/watch! (assoc opts :watcher :polling) groups)))) + (defn alter-watches [{:keys [watcher watches]} f] (when watcher (hawk/stop! watcher)) (let [watches (f watches) watcher (when (not-empty watches) (if *hawk-options* - (apply hawk/watch! *hawk-options* (map vector (vals watches))) - (apply hawk/watch! (map vector (vals watches)))))] + (apply watch-with-fallback! *hawk-options* (map vector (vals watches))) + (apply watch-with-fallback! (map vector (vals watches)))))] {:watcher watcher :watches watches}))