Axle is an efficient cross-platform DirectoryWatcher based service for Clojure.
BarbaryWatchService for Mac is considered deprecated and no longers
works with newer versions of Java. This means existing watcher
implementations that depend on it, like
Hawk, no longer perform well. Axle
introduces a axle.core/watch!
fn that is a thin wrapper of the
cross-platform, high performance
DirectoryWatcher.
Just add the following dependency in your deps.edn
:
io.zalky/axle {:mvn/version "0.2.1"}
You can start a watch task like so:
(require '[axle.core :as axle])
(def watcher
(axle/watch!
{:paths ["src/clojure" "src/assets"]
:context {:init "context"}
:handler (fn [context event]
(update-context ...))}))
Where :handler
is a reducing function that accepts the current
context and a file event to return an updated context, :paths
is a
list of paths (to individual files or directories) to watch, and
optionally, :context
is the initial value of the accumulated
context.
File events have the following form:
{:type :modify,
:path "/path/to/file.clj",
:count 1,
:root-path "src",
:directory? false,
There are four event types, :create
, :delete
, :modify
and
:overflow
(which is emitted if the file system is generating events
faster than the underlying implementation can process them).
Each event can optionally include a file hash. Since this affects
performance it is disabled by default, but can be turned on via the
:file-hashing true
option:
(def watcher
(axle/watch!
{:paths ["src/clojure" "src/assets"]
:handler handler
:file-hashing true}))
Now events will include an additional :hash
attribute.
On uncaught exceptions, watch!
will print a stacktrace that includes
the context at the time of the error. However, you should consider
catching errors in your handler, where you have access to both the
context and the event, and also have the option to update the context
in response to an error.
Finally, a watch task can be stopped via:
(axle/stop! watcher)
You can return a windowing handler, which handles a collection of events that have occurred within a certain number of milliseconds, via:
{:handler (axle/window ms (fn handler [context events] ...))}
Where events
is just a sequence of event maps, and ms
is just an
integer number of milliseconds.
Beholder is a similar
DirectoryWatcher
based wrapper. However, its callback is not a
reducing function, so you cannot accumulate a context, and it does not
provide windowing functionality.
Axle is distributed under the terms of the Apache License 2.0.